blob: c9fb49289d48183aaeee34b574ed815a4b67f78a [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
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_receiver.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> //assert
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000014#include <string.h> //memset
niklase@google.com470e71d2011-07-07 08:21:25 +000015
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000016#include <algorithm>
17
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000018#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
19#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
20#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
21#include "webrtc/system_wrappers/interface/trace.h"
22#include "webrtc/system_wrappers/interface/trace_event.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000023
niklase@google.com470e71d2011-07-07 08:21:25 +000024namespace webrtc {
25using namespace RTCPUtility;
26using namespace RTCPHelp;
27
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000028// The number of RTCP time intervals needed to trigger a timeout.
29const int kRrTimeoutIntervals = 3;
30
pbos@webrtc.org2f446732013-04-08 11:08:41 +000031RTCPReceiver::RTCPReceiver(const int32_t id, Clock* clock,
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000032 ModuleRtpRtcpImpl* owner)
33 : TMMBRHelp(),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000034 _id(id),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000035 _clock(clock),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000036 _method(kRtcpOff),
37 _lastReceived(0),
38 _rtpRtcp(*owner),
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000039 _criticalSectionFeedbacks(
40 CriticalSectionWrapper::CreateCriticalSection()),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000041 _cbRtcpFeedback(NULL),
42 _cbRtcpBandwidthObserver(NULL),
43 _cbRtcpIntraFrameObserver(NULL),
44 _criticalSectionRTCPReceiver(
45 CriticalSectionWrapper::CreateCriticalSection()),
stefan@webrtc.org28a331e2013-09-17 07:49:56 +000046 main_ssrc_(0),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000047 _remoteSSRC(0),
48 _remoteSenderInfo(),
49 _lastReceivedSRNTPsecs(0),
50 _lastReceivedSRNTPfrac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000051 _lastReceivedXRNTPsecs(0),
52 _lastReceivedXRNTPfrac(0),
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +000053 xr_rr_rtt_ms_(0),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000054 _receivedInfoMap(),
55 _packetTimeOutMS(0),
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000056 _lastReceivedRrMs(0),
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +000057 _lastIncreasedSequenceNumberMs(0),
58 stats_callback_(NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +000059 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
60 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
61}
62
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000063RTCPReceiver::~RTCPReceiver() {
64 delete _criticalSectionRTCPReceiver;
65 delete _criticalSectionFeedbacks;
niklase@google.com470e71d2011-07-07 08:21:25 +000066
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000067 while (!_receivedReportBlockMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000068 std::map<uint32_t, RTCPReportBlockInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000069 _receivedReportBlockMap.begin();
70 delete first->second;
71 _receivedReportBlockMap.erase(first);
72 }
73 while (!_receivedInfoMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000074 std::map<uint32_t, RTCPReceiveInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000075 _receivedInfoMap.begin();
76 delete first->second;
77 _receivedInfoMap.erase(first);
78 }
79 while (!_receivedCnameMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000080 std::map<uint32_t, RTCPCnameInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000081 _receivedCnameMap.begin();
82 delete first->second;
83 _receivedCnameMap.erase(first);
84 }
85 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id,
86 "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +000087}
88
89void
pbos@webrtc.org2f446732013-04-08 11:08:41 +000090RTCPReceiver::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +000091{
92 _id = id;
93}
94
95RTCPMethod
96RTCPReceiver::Status() const
97{
98 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
99 return _method;
100}
101
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000102int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000103RTCPReceiver::SetRTCPStatus(const RTCPMethod method)
104{
105 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
106 _method = method;
107 return 0;
108}
109
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000110int64_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000111RTCPReceiver::LastReceived()
112{
113 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
114 return _lastReceived;
115}
116
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000117int64_t
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000118RTCPReceiver::LastReceivedReceiverReport() const {
119 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000120 int64_t last_received_rr = -1;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000121 for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin();
122 it != _receivedInfoMap.end(); ++it) {
123 if (it->second->lastTimeReceived > last_received_rr) {
124 last_received_rr = it->second->lastTimeReceived;
125 }
126 }
127 return last_received_rr;
128}
129
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000130int32_t
131RTCPReceiver::SetRemoteSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000132{
133 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
134
135 // new SSRC reset old reports
136 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
137 _lastReceivedSRNTPsecs = 0;
138 _lastReceivedSRNTPfrac = 0;
139
140 _remoteSSRC = ssrc;
141 return 0;
142}
143
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000144uint32_t RTCPReceiver::RemoteSSRC() const {
145 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
146 return _remoteSSRC;
147}
148
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000149void RTCPReceiver::RegisterRtcpObservers(
150 RtcpIntraFrameObserver* intra_frame_callback,
151 RtcpBandwidthObserver* bandwidth_callback,
152 RtcpFeedback* feedback_callback) {
153 CriticalSectionScoped lock(_criticalSectionFeedbacks);
154 _cbRtcpIntraFrameObserver = intra_frame_callback;
155 _cbRtcpBandwidthObserver = bandwidth_callback;
156 _cbRtcpFeedback = feedback_callback;
niklase@google.com470e71d2011-07-07 08:21:25 +0000157}
158
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000159void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
160 const std::set<uint32_t>& registered_ssrcs) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000161 uint32_t old_ssrc = 0;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000162 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000163 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000164 old_ssrc = main_ssrc_;
165 main_ssrc_ = main_ssrc;
166 registered_ssrcs_ = registered_ssrcs;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000167 }
168 {
169 CriticalSectionScoped lock(_criticalSectionFeedbacks);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000170 if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) {
171 _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc);
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000172 }
173 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000174}
175
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000176int32_t RTCPReceiver::ResetRTT(const uint32_t remoteSSRC) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000177 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
178 RTCPReportBlockInformation* reportBlock =
179 GetReportBlockInformation(remoteSSRC);
180 if (reportBlock == NULL) {
181 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
182 "\tfailed to GetReportBlockInformation(%u)", remoteSSRC);
183 return -1;
184 }
185 reportBlock->RTT = 0;
186 reportBlock->avgRTT = 0;
187 reportBlock->minRTT = 0;
188 reportBlock->maxRTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000189 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000190}
191
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000192int32_t RTCPReceiver::RTT(uint32_t remoteSSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000193 uint16_t* RTT,
194 uint16_t* avgRTT,
195 uint16_t* minRTT,
196 uint16_t* maxRTT) const {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000197 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000198
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000199 RTCPReportBlockInformation* reportBlock =
200 GetReportBlockInformation(remoteSSRC);
201
202 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000203 return -1;
204 }
205 if (RTT) {
206 *RTT = reportBlock->RTT;
207 }
208 if (avgRTT) {
209 *avgRTT = reportBlock->avgRTT;
210 }
211 if (minRTT) {
212 *minRTT = reportBlock->minRTT;
213 }
214 if (maxRTT) {
215 *maxRTT = reportBlock->maxRTT;
216 }
217 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000218}
219
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000220bool RTCPReceiver::GetAndResetXrRrRtt(uint16_t* rtt_ms) {
221 assert(rtt_ms);
222 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
223 if (xr_rr_rtt_ms_ == 0) {
224 return false;
225 }
226 *rtt_ms = xr_rr_rtt_ms_;
227 xr_rr_rtt_ms_ = 0;
228 return true;
229}
230
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000231int32_t
232RTCPReceiver::NTP(uint32_t *ReceivedNTPsecs,
233 uint32_t *ReceivedNTPfrac,
234 uint32_t *RTCPArrivalTimeSecs,
235 uint32_t *RTCPArrivalTimeFrac,
236 uint32_t *rtcp_timestamp) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000237{
238 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
239 if(ReceivedNTPsecs)
240 {
241 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
242 }
243 if(ReceivedNTPfrac)
244 {
245 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
246 }
247 if(RTCPArrivalTimeFrac)
248 {
249 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
250 }
251 if(RTCPArrivalTimeSecs)
252 {
253 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
254 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000255 if (rtcp_timestamp) {
256 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
257 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000258 return 0;
259}
260
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000261bool RTCPReceiver::LastReceivedXrReferenceTimeInfo(
262 RtcpReceiveTimeInfo* info) const {
263 assert(info);
264 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
265 if (_lastReceivedXRNTPsecs == 0 && _lastReceivedXRNTPfrac == 0) {
266 return false;
267 }
268
269 info->sourceSSRC = _remoteXRReceiveTimeInfo.sourceSSRC;
270 info->lastRR = _remoteXRReceiveTimeInfo.lastRR;
271
272 // Get the delay since last received report (RFC 3611).
273 uint32_t receive_time = RTCPUtility::MidNtp(_lastReceivedXRNTPsecs,
274 _lastReceivedXRNTPfrac);
275
276 uint32_t ntp_sec = 0;
277 uint32_t ntp_frac = 0;
278 _clock->CurrentNtp(ntp_sec, ntp_frac);
279 uint32_t now = RTCPUtility::MidNtp(ntp_sec, ntp_frac);
280
281 info->delaySinceLastRR = now - receive_time;
282 return true;
283}
284
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000285int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000286RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const
287{
288 if(senderInfo == NULL)
289 {
290 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
291 return -1;
292 }
293 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
294 if(_lastReceivedSRNTPsecs == 0)
295 {
296 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s No received SR", __FUNCTION__);
297 return -1;
298 }
299 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
300 return 0;
301}
302
303// statistics
304// we can get multiple receive reports when we receive the report from a CE
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000305int32_t RTCPReceiver::StatisticsReceived(
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000306 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000307 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000308 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
309
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000310 std::map<uint32_t, RTCPReportBlockInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000311 _receivedReportBlockMap.begin();
312
313 while (it != _receivedReportBlockMap.end()) {
314 receiveBlocks->push_back(it->second->remoteReceiveBlock);
315 it++;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000316 }
317 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000318}
319
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000320int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000321RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
322 RTCPUtility::RTCPParserV2* rtcpParser)
323{
324 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
325
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000326 _lastReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000327
328 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
329 while (pktType != RTCPUtility::kRtcpNotValidCode)
330 {
331 // Each "case" is responsible for iterate the parser to the
332 // next top level packet.
333 switch (pktType)
334 {
335 case RTCPUtility::kRtcpSrCode:
336 case RTCPUtility::kRtcpRrCode:
337 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
338 break;
339 case RTCPUtility::kRtcpSdesCode:
340 HandleSDES(*rtcpParser);
341 break;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000342 case RTCPUtility::kRtcpXrHeaderCode:
343 HandleXrHeader(*rtcpParser, rtcpPacketInformation);
344 break;
345 case RTCPUtility::kRtcpXrReceiverReferenceTimeCode:
346 HandleXrReceiveReferenceTime(*rtcpParser, rtcpPacketInformation);
347 break;
348 case RTCPUtility::kRtcpXrDlrrReportBlockCode:
349 HandleXrDlrrReportBlock(*rtcpParser, rtcpPacketInformation);
350 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000351 case RTCPUtility::kRtcpXrVoipMetricCode:
352 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
353 break;
354 case RTCPUtility::kRtcpByeCode:
355 HandleBYE(*rtcpParser);
356 break;
357 case RTCPUtility::kRtcpRtpfbNackCode:
358 HandleNACK(*rtcpParser, rtcpPacketInformation);
359 break;
360 case RTCPUtility::kRtcpRtpfbTmmbrCode:
361 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
362 break;
363 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000364 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000365 break;
366 case RTCPUtility::kRtcpRtpfbSrReqCode:
367 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
368 break;
369 case RTCPUtility::kRtcpPsfbPliCode:
370 HandlePLI(*rtcpParser, rtcpPacketInformation);
371 break;
372 case RTCPUtility::kRtcpPsfbSliCode:
373 HandleSLI(*rtcpParser, rtcpPacketInformation);
374 break;
375 case RTCPUtility::kRtcpPsfbRpsiCode:
376 HandleRPSI(*rtcpParser, rtcpPacketInformation);
377 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000378 case RTCPUtility::kRtcpExtendedIjCode:
379 HandleIJ(*rtcpParser, rtcpPacketInformation);
380 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000381 case RTCPUtility::kRtcpPsfbFirCode:
382 HandleFIR(*rtcpParser, rtcpPacketInformation);
383 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000384 case RTCPUtility::kRtcpPsfbAppCode:
385 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
386 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000387 case RTCPUtility::kRtcpAppCode:
388 // generic application messages
389 HandleAPP(*rtcpParser, rtcpPacketInformation);
390 break;
391 case RTCPUtility::kRtcpAppItemCode:
392 // generic application messages
393 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
394 break;
395 default:
396 rtcpParser->Iterate();
397 break;
398 }
399 pktType = rtcpParser->PacketType();
400 }
401 return 0;
402}
403
404// no need for critsect we have _criticalSectionRTCPReceiver
405void
406RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
407 RTCPPacketInformation& rtcpPacketInformation)
408{
409 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
410 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
411
412 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
413
414 // SR.SenderSSRC
415 // The synchronization source identifier for the originator of this SR packet
416
417 // rtcpPacket.RR.SenderSSRC
418 // The source of the packet sender, same as of SR? or is this a CE?
419
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000420 const uint32_t remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
421 const uint8_t numberOfReportBlocks = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.NumberOfReportBlocks:rtcpPacket.SR.NumberOfReportBlocks;
niklase@google.com470e71d2011-07-07 08:21:25 +0000422
423 rtcpPacketInformation.remoteSSRC = remoteSSRC;
424
425 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
426 if (!ptrReceiveInfo)
427 {
428 rtcpParser.Iterate();
429 return;
430 }
431
432 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
433 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000434 TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
435 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000436 "ssrc", main_ssrc_);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000437
niklase@google.com470e71d2011-07-07 08:21:25 +0000438 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
439 {
440 // only signal that we have received a SR when we accept one
441 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
442
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000443 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
444 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
445 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
446
niklase@google.com470e71d2011-07-07 08:21:25 +0000447 // We will only store the send report from one source, but
448 // we will store all the receive block
449
450 // Save the NTP time of this report
451 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
452 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
453 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
454 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
455 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
456
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000457 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000458 }
459 else
460 {
461 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
462 }
463 } else
464 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000465 TRACE_EVENT_INSTANT2("webrtc_rtp", "RR",
466 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000467 "ssrc", main_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000468
469 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
470 }
471 UpdateReceiveInformation(*ptrReceiveInfo);
472
473 rtcpPacketType = rtcpParser.Iterate();
474
475 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
476 {
477 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC, numberOfReportBlocks);
478 rtcpPacketType = rtcpParser.Iterate();
479 }
480}
481
482// no need for critsect we have _criticalSectionRTCPReceiver
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000483void RTCPReceiver::HandleReportBlock(
484 const RTCPUtility::RTCPPacket& rtcpPacket,
485 RTCPPacketInformation& rtcpPacketInformation,
486 const uint32_t remoteSSRC,
487 const uint8_t numberOfReportBlocks)
488 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000489 // This will be called once per report block in the RTCP packet.
490 // We filter out all report blocks that are not for us.
491 // Each packet has max 31 RR blocks.
492 //
493 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000494
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000495 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
496 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000497
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000498 // Filter out all report blocks that are not for us.
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000499 if (registered_ssrcs_.find(rtcpPacket.ReportBlockItem.SSRC) ==
500 registered_ssrcs_.end()) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000501 // This block is not for us ignore it.
502 return;
503 }
504
505 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
506 // _criticalSectionRTCPReceiver.
507 _criticalSectionRTCPReceiver->Leave();
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000508 uint32_t sendTimeMS =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000509 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
510 _criticalSectionRTCPReceiver->Enter();
511
512 RTCPReportBlockInformation* reportBlock =
513 CreateReportBlockInformation(remoteSSRC);
514 if (reportBlock == NULL) {
515 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
516 "\tfailed to CreateReportBlockInformation(%u)", remoteSSRC);
517 return;
518 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000519
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000520 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000521 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
522 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
523 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
524 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
525 reportBlock->remoteReceiveBlock.cumulativeLost =
526 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000527 if (rb.ExtendedHighestSequenceNumber >
528 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
529 // We have successfully delivered new RTP packets to the remote side after
530 // the last RR was sent from the remote side.
531 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000532 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000533 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
534 rb.ExtendedHighestSequenceNumber;
535 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
536 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
537 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
538
539 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
540 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
541 }
542
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000543 uint32_t delaySinceLastSendReport =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000544 rtcpPacket.ReportBlockItem.DelayLastSR;
545
546 // local NTP time when we received this
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000547 uint32_t lastReceivedRRNTPsecs = 0;
548 uint32_t lastReceivedRRNTPfrac = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000549
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000550 _clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000551
552 // time when we received this in MS
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000553 uint32_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
554 lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000555
556 // Estimate RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000557 uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000558 d /= 65536;
559 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
560
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000561 int32_t RTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000562
563 if (sendTimeMS > 0) {
564 RTT = receiveTimeMS - d - sendTimeMS;
565 if (RTT <= 0) {
566 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000567 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000568 if (RTT > reportBlock->maxRTT) {
569 // store max RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000570 reportBlock->maxRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000571 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000572 if (reportBlock->minRTT == 0) {
573 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000574 reportBlock->minRTT = (uint16_t) RTT;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000575 } else if (RTT < reportBlock->minRTT) {
576 // Store min RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000577 reportBlock->minRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000578 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000579 // store last RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000580 reportBlock->RTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000581
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000582 // store average RTT
583 if (reportBlock->numAverageCalcs != 0) {
584 float ac = static_cast<float> (reportBlock->numAverageCalcs);
585 float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT)
586 + ((1 / (ac + 1)) * RTT);
587 reportBlock->avgRTT = static_cast<int> (newAverage + 0.5f);
588 } else {
589 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000590 reportBlock->avgRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000591 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000592 reportBlock->numAverageCalcs++;
593 }
594
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000595 TRACE_COUNTER_ID1("webrtc_rtp", "RR_RTT", rb.SSRC, RTT);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000596
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000597 rtcpPacketInformation.AddReportInfo(*reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000598}
599
600RTCPReportBlockInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000601RTCPReceiver::CreateReportBlockInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000602 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000603
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000604 std::map<uint32_t, RTCPReportBlockInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000605 _receivedReportBlockMap.find(remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000606
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000607 RTCPReportBlockInformation* ptrReportBlockInfo = NULL;
608 if (it != _receivedReportBlockMap.end()) {
609 ptrReportBlockInfo = it->second;
610 } else {
611 ptrReportBlockInfo = new RTCPReportBlockInformation;
612 _receivedReportBlockMap[remoteSSRC] = ptrReportBlockInfo;
613 }
614 return ptrReportBlockInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000615}
616
617RTCPReportBlockInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000618RTCPReceiver::GetReportBlockInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000619 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000620
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000621 std::map<uint32_t, RTCPReportBlockInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000622 _receivedReportBlockMap.find(remoteSSRC);
623
624 if (it == _receivedReportBlockMap.end()) {
625 return NULL;
626 }
627 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000628}
629
630RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000631RTCPReceiver::CreateCnameInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000632 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000633
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000634 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000635 _receivedCnameMap.find(remoteSSRC);
636
637 if (it != _receivedCnameMap.end()) {
638 return it->second;
639 }
640 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000641 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000642 _receivedCnameMap[remoteSSRC] = cnameInfo;
643 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000644}
645
646RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000647RTCPReceiver::GetCnameInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000648 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000649
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000650 std::map<uint32_t, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000651 _receivedCnameMap.find(remoteSSRC);
652
653 if (it == _receivedCnameMap.end()) {
654 return NULL;
655 }
656 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000657}
658
659RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000660RTCPReceiver::CreateReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000661 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000662
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000663 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000664 _receivedInfoMap.find(remoteSSRC);
665
666 if (it != _receivedInfoMap.end()) {
667 return it->second;
668 }
669 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
670 _receivedInfoMap[remoteSSRC] = receiveInfo;
671 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000672}
673
674RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000675RTCPReceiver::GetReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000676 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000677
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000678 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000679 _receivedInfoMap.find(remoteSSRC);
680 if (it == _receivedInfoMap.end()) {
681 return NULL;
682 }
683 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000684}
685
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000686void RTCPReceiver::UpdateReceiveInformation(
687 RTCPReceiveInformation& receiveInformation) {
688 // Update that this remote is alive
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000689 receiveInformation.lastTimeReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000690}
691
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000692bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
693 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
694 if (_lastReceivedRrMs == 0)
695 return false;
696
697 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000698 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000699 // Reset the timer to only trigger one log.
700 _lastReceivedRrMs = 0;
701 return true;
702 }
703 return false;
704}
705
706bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
707 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
708 if (_lastIncreasedSequenceNumberMs == 0)
709 return false;
710
711 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000712 if (_clock->TimeInMilliseconds() > _lastIncreasedSequenceNumberMs +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000713 time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000714 // Reset the timer to only trigger one log.
715 _lastIncreasedSequenceNumberMs = 0;
716 return true;
717 }
718 return false;
719}
720
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000721bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
722 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000723
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000724 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000725 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000726
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000727 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000728 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000729
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000730 while (receiveInfoIt != _receivedInfoMap.end()) {
731 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
732 if (receiveInfo == NULL) {
733 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000734 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000735 // time since last received rtcp packet
736 // when we dont have a lastTimeReceived and the object is marked
737 // readyForDelete it's removed from the map
738 if (receiveInfo->lastTimeReceived) {
739 /// use audio define since we don't know what interval the remote peer is
740 // using
741 if ((timeNow - receiveInfo->lastTimeReceived) >
742 5 * RTCP_INTERVAL_AUDIO_MS) {
743 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000744 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000745 // prevent that we call this over and over again
746 receiveInfo->lastTimeReceived = 0;
747 // send new TMMBN to all channels using the default codec
748 updateBoundingSet = true;
749 }
750 receiveInfoIt++;
751 } else if (receiveInfo->readyForDelete) {
752 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000753 std::map<uint32_t, RTCPReceiveInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000754 receiveInfoItemToBeErased = receiveInfoIt;
755 receiveInfoIt++;
756 delete receiveInfoItemToBeErased->second;
757 _receivedInfoMap.erase(receiveInfoItemToBeErased);
758 } else {
759 receiveInfoIt++;
760 }
761 }
762 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000763}
764
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000765int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000766 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000767
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000768 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000769 _receivedInfoMap.find(_remoteSSRC);
770
771 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000772 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000773 }
774 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
775 if (receiveInfo == NULL) {
776 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
777 "%s failed to get RTCPReceiveInformation",
778 __FUNCTION__);
779 return -1;
780 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000781 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000782 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000783 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000784 for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000785 i++) {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000786 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000787 // owner of bounding set
788 tmmbrOwner = true;
789 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000790 boundingSetRec->SetEntry(i,
791 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
792 receiveInfo->TmmbnBoundingSet.PacketOH(i),
793 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000794 }
795 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000796 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000797}
798
799// no need for critsect we have _criticalSectionRTCPReceiver
800void
801RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser)
802{
803 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
804 while (pktType == RTCPUtility::kRtcpSdesChunkCode)
805 {
806 HandleSDESChunk(rtcpParser);
807 pktType = rtcpParser.Iterate();
808 }
809}
810
811// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000812void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
813 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
814 RTCPCnameInformation* cnameInfo =
815 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
816 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000817
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000818 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
819 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000820}
821
822// no need for critsect we have _criticalSectionRTCPReceiver
823void
824RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
825 RTCPPacketInformation& rtcpPacketInformation)
826{
827 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000828 if (main_ssrc_ != rtcpPacket.NACK.MediaSSRC)
niklase@google.com470e71d2011-07-07 08:21:25 +0000829 {
830 // Not to us.
831 rtcpParser.Iterate();
832 return;
833 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000834 rtcpPacketInformation.ResetNACKPacketIdArray();
835
836 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
837 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode)
838 {
839 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
840 pktType = rtcpParser.Iterate();
841 }
842}
843
844// no need for critsect we have _criticalSectionRTCPReceiver
845void
846RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
847 RTCPPacketInformation& rtcpPacketInformation)
848{
849 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
850
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000851 uint16_t bitMask = rtcpPacket.NACKItem.BitMask;
niklase@google.com470e71d2011-07-07 08:21:25 +0000852 if(bitMask)
853 {
854 for(int i=1; i <= 16; ++i)
855 {
856 if(bitMask & 0x01)
857 {
858 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
859 }
860 bitMask = bitMask >>1;
861 }
862 }
863
864 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
865}
866
867// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000868void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
869 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000870
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000871 // clear our lists
872 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000873 std::map<uint32_t, RTCPReportBlockInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000874 reportBlockInfoIt = _receivedReportBlockMap.find(
875 rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000876
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000877 if (reportBlockInfoIt != _receivedReportBlockMap.end()) {
878 delete reportBlockInfoIt->second;
879 _receivedReportBlockMap.erase(reportBlockInfoIt);
880 }
881 // we can't delete it due to TMMBR
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000882 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000883 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000884
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000885 if (receiveInfoIt != _receivedInfoMap.end()) {
886 receiveInfoIt->second->readyForDelete = true;
887 }
888
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000889 std::map<uint32_t, RTCPCnameInformation*>::iterator cnameInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000890 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
891
892 if (cnameInfoIt != _receivedCnameMap.end()) {
893 delete cnameInfoIt->second;
894 _receivedCnameMap.erase(cnameInfoIt);
895 }
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000896 xr_rr_rtt_ms_ = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000897 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000898}
899
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000900void RTCPReceiver::HandleXrHeader(
901 RTCPUtility::RTCPParserV2& parser,
902 RTCPPacketInformation& rtcpPacketInformation) {
903 const RTCPUtility::RTCPPacket& packet = parser.Packet();
904
905 rtcpPacketInformation.xr_originator_ssrc = packet.XR.OriginatorSSRC;
906
907 parser.Iterate();
908}
909
910void RTCPReceiver::HandleXrReceiveReferenceTime(
911 RTCPUtility::RTCPParserV2& parser,
912 RTCPPacketInformation& rtcpPacketInformation) {
913 const RTCPUtility::RTCPPacket& packet = parser.Packet();
914
915 _remoteXRReceiveTimeInfo.sourceSSRC =
916 rtcpPacketInformation.xr_originator_ssrc;
917
918 _remoteXRReceiveTimeInfo.lastRR = RTCPUtility::MidNtp(
919 packet.XRReceiverReferenceTimeItem.NTPMostSignificant,
920 packet.XRReceiverReferenceTimeItem.NTPLeastSignificant);
921
922 _clock->CurrentNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);
923
924 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
925
926 parser.Iterate();
927}
928
929void RTCPReceiver::HandleXrDlrrReportBlock(
930 RTCPUtility::RTCPParserV2& parser,
931 RTCPPacketInformation& rtcpPacketInformation) {
932 const RTCPUtility::RTCPPacket& packet = parser.Packet();
933 // Iterate through sub-block(s), if any.
934 RTCPUtility::RTCPPacketTypes packet_type = parser.Iterate();
935
936 while (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
937 HandleXrDlrrReportBlockItem(packet, rtcpPacketInformation);
938 packet_type = parser.Iterate();
939 }
940}
941
942void RTCPReceiver::HandleXrDlrrReportBlockItem(
943 const RTCPUtility::RTCPPacket& packet,
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000944 RTCPPacketInformation& rtcpPacketInformation)
945 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000946 if (registered_ssrcs_.find(packet.XRDLRRReportBlockItem.SSRC) ==
947 registered_ssrcs_.end()) {
948 // Not to us.
949 return;
950 }
951
952 rtcpPacketInformation.xr_dlrr_item = true;
953
954 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
955 // _criticalSectionRTCPReceiver.
956 _criticalSectionRTCPReceiver->Leave();
957
958 int64_t send_time_ms;
959 bool found = _rtpRtcp.SendTimeOfXrRrReport(
960 packet.XRDLRRReportBlockItem.LastRR, &send_time_ms);
961
962 _criticalSectionRTCPReceiver->Enter();
963
964 if (!found) {
965 return;
966 }
967
968 // The DelayLastRR field is in units of 1/65536 sec.
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000969 uint32_t delay_rr_ms =
970 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0x0000ffff) * 1000) >> 16) +
971 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0xffff0000) >> 16) * 1000);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000972
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000973 int32_t rtt = _clock->CurrentNtpInMilliseconds() - delay_rr_ms - send_time_ms;
974
975 xr_rr_rtt_ms_ = static_cast<uint16_t>(std::max(rtt, 1));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000976
977 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
978}
979
niklase@google.com470e71d2011-07-07 08:21:25 +0000980// no need for critsect we have _criticalSectionRTCPReceiver
981void
982RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
983 RTCPPacketInformation& rtcpPacketInformation)
984{
985 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
986
987 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
988
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000989 if(rtcpPacket.XRVOIPMetricItem.SSRC == main_ssrc_)
niklase@google.com470e71d2011-07-07 08:21:25 +0000990 {
991 // Store VoIP metrics block if it's about me
992 // from OriginatorSSRC do we filter it?
993 // rtcpPacket.XR.OriginatorSSRC;
994
995 RTCPVoIPMetric receivedVoIPMetrics;
996 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
997 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
998 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
999 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
1000 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
1001 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
1002 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
1003 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
1004 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
1005 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
1006 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
1007 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
1008 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
1009 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
1010 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
1011 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
1012 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
1013 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
1014 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
1015 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
1016
1017 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
1018
1019 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
1020 }
1021 rtcpParser.Iterate();
1022}
1023
1024// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001025void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
1026 RTCPPacketInformation& rtcpPacketInformation) {
1027 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001028 if (main_ssrc_ == rtcpPacket.PLI.MediaSSRC) {
justinlin@chromium.org7bfb3a32013-05-13 22:59:00 +00001029 TRACE_EVENT_INSTANT0("webrtc_rtp", "PLI");
1030
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001031 // Received a signal that we need to send a new key frame.
1032 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
1033 }
1034 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001035}
1036
1037// no need for critsect we have _criticalSectionRTCPReceiver
1038void
1039RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
1040 RTCPPacketInformation& rtcpPacketInformation)
1041{
1042 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1043
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001044 uint32_t senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001045 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
1046 if (ptrReceiveInfo == NULL)
1047 {
1048 // This remote SSRC must be saved before.
1049 rtcpParser.Iterate();
1050 return;
1051 }
1052 if(rtcpPacket.TMMBR.MediaSSRC)
1053 {
1054 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
1055 // in relay mode this is a valid number
1056 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
1057 }
1058
1059 // Use packet length to calc max number of TMMBR blocks
1060 // each TMMBR block is 8 bytes
1061 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
1062
1063 // sanity
1064 if(maxNumOfTMMBRBlocks > 200) // we can't have more than what's in one packet
1065 {
1066 assert(false);
1067 rtcpParser.Iterate();
1068 return;
1069 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001070 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((uint32_t)maxNumOfTMMBRBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001071
1072 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1073 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode)
1074 {
1075 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
1076 pktType = rtcpParser.Iterate();
1077 }
1078}
1079
1080// no need for critsect we have _criticalSectionRTCPReceiver
1081void
1082RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
1083 const RTCPUtility::RTCPPacket& rtcpPacket,
1084 RTCPPacketInformation& rtcpPacketInformation,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001085 const uint32_t senderSSRC)
niklase@google.com470e71d2011-07-07 08:21:25 +00001086{
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001087 if (main_ssrc_ == rtcpPacket.TMMBRItem.SSRC &&
niklase@google.com470e71d2011-07-07 08:21:25 +00001088 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
1089 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001090 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001091 _clock->TimeInMilliseconds());
niklase@google.com470e71d2011-07-07 08:21:25 +00001092 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
1093 }
1094}
1095
1096// no need for critsect we have _criticalSectionRTCPReceiver
1097void
hta@webrtc.org9d54cd12012-04-30 08:24:55 +00001098RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
1099 RTCPPacketInformation& rtcpPacketInformation)
niklase@google.com470e71d2011-07-07 08:21:25 +00001100{
1101 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1102 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.TMMBN.SenderSSRC);
1103 if (ptrReceiveInfo == NULL)
1104 {
1105 // This remote SSRC must be saved before.
1106 rtcpParser.Iterate();
1107 return;
1108 }
hta@webrtc.org9d54cd12012-04-30 08:24:55 +00001109 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +00001110 // Use packet length to calc max number of TMMBN blocks
1111 // each TMMBN block is 8 bytes
1112 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
1113
1114 // sanity
1115 if(maxNumOfTMMBNBlocks > 200) // we cant have more than what's in one packet
1116 {
1117 assert(false);
1118 rtcpParser.Iterate();
1119 return;
1120 }
1121
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001122 ptrReceiveInfo->VerifyAndAllocateBoundingSet((uint32_t)maxNumOfTMMBNBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001123
1124 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1125 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode)
1126 {
1127 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
1128 pktType = rtcpParser.Iterate();
1129 }
1130}
1131
1132// no need for critsect we have _criticalSectionRTCPReceiver
1133void
1134RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
1135 RTCPPacketInformation& rtcpPacketInformation)
1136{
1137 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
1138 rtcpParser.Iterate();
1139}
1140
1141// no need for critsect we have _criticalSectionRTCPReceiver
1142void
1143RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
1144 const RTCPUtility::RTCPPacket& rtcpPacket)
1145{
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001146 receiveInfo.TmmbnBoundingSet.AddEntry(
1147 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
1148 rtcpPacket.TMMBNItem.MeasuredOverhead,
1149 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001150}
1151
1152// no need for critsect we have _criticalSectionRTCPReceiver
1153void
1154RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
1155 RTCPPacketInformation& rtcpPacketInformation)
1156{
1157 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001158 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1159 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode)
1160 {
1161 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1162 pktType = rtcpParser.Iterate();
1163 }
1164}
1165
1166// no need for critsect we have _criticalSectionRTCPReceiver
1167void
1168RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1169 RTCPPacketInformation& rtcpPacketInformation)
1170{
1171 // in theory there could be multiple slices lost
1172 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1173 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
1174}
1175
1176void
1177RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1178 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1179{
1180 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001181 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1182 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1183 {
1184 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1185 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1186 {
1187 // to us unknown
1188 // continue
1189 rtcpParser.Iterate();
1190 return;
1191 }
1192 rtcpPacketInformation.rpsiPictureId = 0;
1193
1194 // convert NativeBitString to rpsiPictureId
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001195 uint8_t numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1196 for(uint8_t n = 0; n < (numberOfBytes-1); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001197 {
1198 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1199 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1200 }
1201 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1202 }
1203}
1204
1205// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001206void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1207 RTCPPacketInformation& rtcpPacketInformation) {
1208 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1209 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1210 pktType = rtcpParser.Iterate();
1211 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1212 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1213 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001214 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001215 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001216}
1217
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001218// no need for critsect we have _criticalSectionRTCPReceiver
1219void
1220RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1221 RTCPPacketInformation& rtcpPacketInformation)
1222{
1223 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1224
1225 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1226 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode)
1227 {
1228 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1229 pktType = rtcpParser.Iterate();
1230 }
1231}
1232
1233void
1234RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1235 RTCPPacketInformation& rtcpPacketInformation)
1236{
1237 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1238 rtcpPacketInformation.interArrivalJitter =
1239 rtcpPacket.ExtendedJitterReportItem.Jitter;
1240}
1241
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001242void RTCPReceiver::HandleREMBItem(
1243 RTCPUtility::RTCPParserV2& rtcpParser,
1244 RTCPPacketInformation& rtcpPacketInformation) {
1245 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1246 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1247 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1248 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001249}
1250
1251// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001252void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1253 RTCPPacketInformation& rtcpPacketInformation) {
1254 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1255 RTCPReceiveInformation* ptrReceiveInfo =
1256 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001257
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001258 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1259 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1260 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1261 pktType = rtcpParser.Iterate();
1262 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001263}
1264
1265// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001266void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1267 const RTCPUtility::RTCPPacket& rtcpPacket,
1268 RTCPPacketInformation& rtcpPacketInformation) {
1269 // Is it our sender that is requested to generate a new keyframe
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001270 if (main_ssrc_ != rtcpPacket.FIRItem.SSRC) {
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001271 return;
1272 }
1273 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1274 // we don't know who this originate from
1275 if (receiveInfo) {
1276 // check if we have reported this FIRSequenceNumber before
1277 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1278 receiveInfo->lastFIRSequenceNumber) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001279 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001280 // sanity; don't go crazy with the callbacks
1281 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1282 receiveInfo->lastFIRRequest = now;
1283 receiveInfo->lastFIRSequenceNumber =
1284 rtcpPacket.FIRItem.CommandSequenceNumber;
1285 // received signal that we need to send a new key frame
1286 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1287 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001288 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001289 } else {
1290 // received signal that we need to send a new key frame
1291 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1292 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001293}
1294
1295void
1296RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1297 RTCPPacketInformation& rtcpPacketInformation)
1298{
1299 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1300
1301 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1302 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1303 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
1304
1305 rtcpParser.Iterate();
1306}
1307
1308void
1309RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1310 RTCPPacketInformation& rtcpPacketInformation)
1311{
1312 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1313
1314 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
1315
1316 rtcpParser.Iterate();
1317}
1318
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001319int32_t RTCPReceiver::UpdateTMMBR() {
1320 int32_t numBoundingSet = 0;
1321 uint32_t bitrate = 0;
1322 uint32_t accNumCandidates = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001323
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001324 int32_t size = TMMBRReceived(0, 0, NULL);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001325 if (size > 0) {
1326 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1327 // Get candidate set from receiver.
1328 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1329 } else {
1330 // Candidate set empty.
1331 VerifyAndAllocateCandidateSet(0); // resets candidate set
1332 }
1333 // Find bounding set
1334 TMMBRSet* boundingSet = NULL;
1335 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1336 if (numBoundingSet == -1) {
1337 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1338 "Failed to find TMMBR bounding set.");
1339 return -1;
1340 }
1341 // Set bounding set
1342 // Inform remote clients about the new bandwidth
1343 // inform the remote client
1344 _rtpRtcp.SetTMMBN(boundingSet);
1345
1346 // might trigger a TMMBN
1347 if (numBoundingSet == 0) {
1348 // owner of max bitrate request has timed out
1349 // empty bounding set has been sent
1350 return 0;
1351 }
1352 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001353 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001354 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001355 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1356 if (_cbRtcpBandwidthObserver) {
1357 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
1358 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id,
1359 "Set TMMBR request:%d kbps", bitrate);
1360 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001361 }
1362 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001363}
1364
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001365void RTCPReceiver::RegisterRtcpStatisticsCallback(
1366 RtcpStatisticsCallback* callback) {
1367 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1368 if (callback != NULL)
1369 assert(stats_callback_ == NULL);
1370 stats_callback_ = callback;
1371}
1372
1373RtcpStatisticsCallback* RTCPReceiver::GetRtcpStatisticsCallback() {
1374 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1375 return stats_callback_;
1376}
1377
niklase@google.com470e71d2011-07-07 08:21:25 +00001378// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001379void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001380 RTCPPacketInformation& rtcpPacketInformation) {
1381 // Process TMMBR and REMB first to avoid multiple callbacks
1382 // to OnNetworkChanged.
1383 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
1384 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1385 "SIG [RTCP] Incoming TMMBR to id:%d", _id);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001386
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001387 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1388 UpdateTMMBR();
1389 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001390 unsigned int local_ssrc = 0;
1391 {
1392 // We don't want to hold this critsect when triggering the callbacks below.
1393 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001394 local_ssrc = main_ssrc_;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001395 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001396 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1397 _rtpRtcp.OnRequestSendReport();
1398 }
1399 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001400 if (rtcpPacketInformation.nackSequenceNumbers.size() > 0) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001401 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1402 "SIG [RTCP] Incoming NACK length:%d",
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001403 rtcpPacketInformation.nackSequenceNumbers.size());
1404 _rtpRtcp.OnReceivedNACK(rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001405 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001406 }
1407 {
1408 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001409
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001410 // We need feedback that we have received a report block(s) so that we
1411 // can generate a new packet in a conference relay scenario, one received
1412 // report can generate several RTCP packets, based on number relayed/mixed
1413 // a send report block should go out to all receivers.
1414 if (_cbRtcpIntraFrameObserver) {
1415 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1416 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1417 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
1418 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1419 "SIG [RTCP] Incoming PLI from SSRC:0x%x",
1420 rtcpPacketInformation.remoteSSRC);
1421 } else {
1422 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1423 "SIG [RTCP] Incoming FIR from SSRC:0x%x",
1424 rtcpPacketInformation.remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001425 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001426 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001427 }
1428 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1429 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001430 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001431 }
1432 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1433 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001434 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001435 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001436 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001437 if (_cbRtcpBandwidthObserver) {
1438 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
1439 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1440 "SIG [RTCP] Incoming REMB:%d",
1441 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1442 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1443 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1444 }
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001445 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1446 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001447 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001448 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001449 rtcpPacketInformation.report_blocks,
1450 rtcpPacketInformation.rtt,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001451 now);
1452 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001453 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001454 if(_cbRtcpFeedback) {
solenberg@webrtc.org91811e22013-06-25 20:36:14 +00001455 if(!(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr)) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001456 _cbRtcpFeedback->OnReceiveReportReceived(_id,
1457 rtcpPacketInformation.remoteSSRC);
1458 }
1459 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpXrVoipMetric) {
1460 _cbRtcpFeedback->OnXRVoIPMetricReceived(_id,
1461 rtcpPacketInformation.VoIPMetric);
1462 }
1463 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpApp) {
1464 _cbRtcpFeedback->OnApplicationDataReceived(_id,
1465 rtcpPacketInformation.applicationSubType,
1466 rtcpPacketInformation.applicationName,
1467 rtcpPacketInformation.applicationLength,
1468 rtcpPacketInformation.applicationData);
1469 }
1470 }
1471 }
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001472
1473 {
1474 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1475 if (stats_callback_) {
1476 for (ReportBlockList::const_iterator it =
1477 rtcpPacketInformation.report_blocks.begin();
1478 it != rtcpPacketInformation.report_blocks.end();
1479 ++it) {
1480 RtcpStatistics stats;
1481 stats.cumulative_lost = it->cumulativeLost;
1482 stats.extended_max_sequence_number = it->extendedHighSeqNum;
1483 stats.fraction_lost = it->fractionLost;
1484 stats.jitter = it->jitter;
1485
1486 stats_callback_->StatisticsUpdated(stats, local_ssrc);
1487 }
1488 }
1489 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001490}
1491
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001492int32_t RTCPReceiver::CNAME(const uint32_t remoteSSRC,
1493 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001494 assert(cName);
1495
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001496 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1497 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001498 if (cnameInfo == NULL) {
1499 return -1;
1500 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001501 cName[RTCP_CNAME_SIZE - 1] = 0;
1502 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1503 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001504}
1505
1506// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001507int32_t RTCPReceiver::TMMBRReceived(const uint32_t size,
1508 const uint32_t accNumCandidates,
1509 TMMBRSet* candidateSet) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001510 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001511
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001512 std::map<uint32_t, RTCPReceiveInformation*>::const_iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001513 receiveInfoIt = _receivedInfoMap.begin();
1514 if (receiveInfoIt == _receivedInfoMap.end()) {
1515 return -1;
1516 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001517 uint32_t num = accNumCandidates;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001518 if (candidateSet) {
1519 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1520 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1521 if (receiveInfo == NULL) {
1522 return 0;
1523 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001524 for (uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001525 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001526 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001527 _clock->TimeInMilliseconds()) == 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001528 num++;
1529 }
1530 }
1531 receiveInfoIt++;
1532 }
1533 } else {
1534 while (receiveInfoIt != _receivedInfoMap.end()) {
1535 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1536 if(receiveInfo == NULL) {
1537 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
1538 "%s failed to get RTCPReceiveInformation",
1539 __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +00001540 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001541 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001542 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001543 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001544 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001545 }
1546 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001547}
1548
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001549} // namespace webrtc