blob: 3978332c22a25700ddf57c5495e96c69a9b7bb3c [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"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000021#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000022#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.orgd16e8392014-12-19 13:49:55 +000031RTCPReceiver::RTCPReceiver(int32_t id, Clock* clock, ModuleRtpRtcpImpl* owner)
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000032 : TMMBRHelp(),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000033 _id(id),
34 _clock(clock),
35 _method(kRtcpOff),
36 _lastReceived(0),
37 _rtpRtcp(*owner),
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000038 _criticalSectionFeedbacks(
39 CriticalSectionWrapper::CreateCriticalSection()),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000040 _cbRtcpBandwidthObserver(NULL),
41 _cbRtcpIntraFrameObserver(NULL),
42 _criticalSectionRTCPReceiver(
43 CriticalSectionWrapper::CreateCriticalSection()),
44 main_ssrc_(0),
45 _remoteSSRC(0),
46 _remoteSenderInfo(),
47 _lastReceivedSRNTPsecs(0),
48 _lastReceivedSRNTPfrac(0),
49 _lastReceivedXRNTPsecs(0),
50 _lastReceivedXRNTPfrac(0),
51 xr_rr_rtt_ms_(0),
52 _receivedInfoMap(),
53 _packetTimeOutMS(0),
54 _lastReceivedRrMs(0),
55 _lastIncreasedSequenceNumberMs(0),
56 stats_callback_(NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +000057 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
niklase@google.com470e71d2011-07-07 08:21:25 +000058}
59
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000060RTCPReceiver::~RTCPReceiver() {
61 delete _criticalSectionRTCPReceiver;
62 delete _criticalSectionFeedbacks;
niklase@google.com470e71d2011-07-07 08:21:25 +000063
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +000064 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
65 for (; it != _receivedReportBlockMap.end(); ++it) {
66 ReportBlockInfoMap* info_map = &(it->second);
67 while (!info_map->empty()) {
68 ReportBlockInfoMap::iterator it_info = info_map->begin();
69 delete it_info->second;
70 info_map->erase(it_info);
71 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000072 }
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 }
niklase@google.com470e71d2011-07-07 08:21:25 +000085}
86
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000087void RTCPReceiver::ChangeUniqueId(int32_t id) {
niklase@google.com470e71d2011-07-07 08:21:25 +000088 _id = id;
89}
90
91RTCPMethod
92RTCPReceiver::Status() const
93{
94 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
95 return _method;
96}
97
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000098void RTCPReceiver::SetRTCPStatus(RTCPMethod method) {
99 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
100 _method = method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000101}
102
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000103int64_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000104RTCPReceiver::LastReceived()
105{
106 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
107 return _lastReceived;
108}
109
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000110int64_t
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000111RTCPReceiver::LastReceivedReceiverReport() const {
112 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000113 int64_t last_received_rr = -1;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000114 for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin();
115 it != _receivedInfoMap.end(); ++it) {
116 if (it->second->lastTimeReceived > last_received_rr) {
117 last_received_rr = it->second->lastTimeReceived;
118 }
119 }
120 return last_received_rr;
121}
122
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000123int32_t RTCPReceiver::SetRemoteSSRC(uint32_t ssrc) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000124 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
125
126 // new SSRC reset old reports
127 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
128 _lastReceivedSRNTPsecs = 0;
129 _lastReceivedSRNTPfrac = 0;
130
131 _remoteSSRC = ssrc;
132 return 0;
133}
134
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000135uint32_t RTCPReceiver::RemoteSSRC() const {
136 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
137 return _remoteSSRC;
138}
139
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000140void RTCPReceiver::RegisterRtcpObservers(
141 RtcpIntraFrameObserver* intra_frame_callback,
pbos@webrtc.orgece38902014-11-14 11:52:04 +0000142 RtcpBandwidthObserver* bandwidth_callback) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000143 CriticalSectionScoped lock(_criticalSectionFeedbacks);
144 _cbRtcpIntraFrameObserver = intra_frame_callback;
145 _cbRtcpBandwidthObserver = bandwidth_callback;
niklase@google.com470e71d2011-07-07 08:21:25 +0000146}
147
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000148void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
149 const std::set<uint32_t>& registered_ssrcs) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000150 uint32_t old_ssrc = 0;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000151 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000152 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000153 old_ssrc = main_ssrc_;
154 main_ssrc_ = main_ssrc;
155 registered_ssrcs_ = registered_ssrcs;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000156 }
157 {
158 CriticalSectionScoped lock(_criticalSectionFeedbacks);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000159 if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) {
160 _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc);
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000161 }
162 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000163}
164
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000165int32_t RTCPReceiver::RTT(uint32_t remoteSSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000166 uint16_t* RTT,
167 uint16_t* avgRTT,
168 uint16_t* minRTT,
169 uint16_t* maxRTT) const {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000170 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000171
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000172 RTCPReportBlockInformation* reportBlock =
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000173 GetReportBlockInformation(remoteSSRC, main_ssrc_);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000174
175 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000176 return -1;
177 }
178 if (RTT) {
179 *RTT = reportBlock->RTT;
180 }
181 if (avgRTT) {
182 *avgRTT = reportBlock->avgRTT;
183 }
184 if (minRTT) {
185 *minRTT = reportBlock->minRTT;
186 }
187 if (maxRTT) {
188 *maxRTT = reportBlock->maxRTT;
189 }
190 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000191}
192
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000193bool RTCPReceiver::GetAndResetXrRrRtt(uint16_t* rtt_ms) {
194 assert(rtt_ms);
195 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
196 if (xr_rr_rtt_ms_ == 0) {
197 return false;
198 }
199 *rtt_ms = xr_rr_rtt_ms_;
200 xr_rr_rtt_ms_ = 0;
201 return true;
202}
203
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000204// TODO(pbos): Make this fail when we haven't received NTP.
205bool RTCPReceiver::NTP(uint32_t* ReceivedNTPsecs,
206 uint32_t* ReceivedNTPfrac,
207 uint32_t* RTCPArrivalTimeSecs,
208 uint32_t* RTCPArrivalTimeFrac,
209 uint32_t* rtcp_timestamp) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000210{
211 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
212 if(ReceivedNTPsecs)
213 {
214 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
215 }
216 if(ReceivedNTPfrac)
217 {
218 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
219 }
220 if(RTCPArrivalTimeFrac)
221 {
222 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
223 }
224 if(RTCPArrivalTimeSecs)
225 {
226 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
227 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000228 if (rtcp_timestamp) {
229 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
230 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000231 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000232}
233
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000234bool RTCPReceiver::LastReceivedXrReferenceTimeInfo(
235 RtcpReceiveTimeInfo* info) const {
236 assert(info);
237 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
238 if (_lastReceivedXRNTPsecs == 0 && _lastReceivedXRNTPfrac == 0) {
239 return false;
240 }
241
242 info->sourceSSRC = _remoteXRReceiveTimeInfo.sourceSSRC;
243 info->lastRR = _remoteXRReceiveTimeInfo.lastRR;
244
245 // Get the delay since last received report (RFC 3611).
246 uint32_t receive_time = RTCPUtility::MidNtp(_lastReceivedXRNTPsecs,
247 _lastReceivedXRNTPfrac);
248
249 uint32_t ntp_sec = 0;
250 uint32_t ntp_frac = 0;
251 _clock->CurrentNtp(ntp_sec, ntp_frac);
252 uint32_t now = RTCPUtility::MidNtp(ntp_sec, ntp_frac);
253
254 info->delaySinceLastRR = now - receive_time;
255 return true;
256}
257
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000258int32_t RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const {
259 assert(senderInfo);
260 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
261 if (_lastReceivedSRNTPsecs == 0) {
262 return -1;
263 }
264 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
265 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000266}
267
268// statistics
269// we can get multiple receive reports when we receive the report from a CE
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000270int32_t RTCPReceiver::StatisticsReceived(
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000271 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000272 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000273 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000274 ReportBlockMap::const_iterator it = _receivedReportBlockMap.begin();
275 for (; it != _receivedReportBlockMap.end(); ++it) {
276 const ReportBlockInfoMap* info_map = &(it->second);
277 ReportBlockInfoMap::const_iterator it_info = info_map->begin();
278 for (; it_info != info_map->end(); ++it_info) {
279 receiveBlocks->push_back(it_info->second->remoteReceiveBlock);
280 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000281 }
282 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000283}
284
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000285void RTCPReceiver::GetPacketTypeCounter(
286 RtcpPacketTypeCounter* packet_counter) const {
287 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
288 *packet_counter = packet_type_counter_;
289}
290
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000291int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000292RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
293 RTCPUtility::RTCPParserV2* rtcpParser)
294{
295 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
296
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000297 _lastReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000298
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000299 if (packet_type_counter_.first_packet_time_ms == -1) {
300 packet_type_counter_.first_packet_time_ms = _lastReceived;
301 }
302
niklase@google.com470e71d2011-07-07 08:21:25 +0000303 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
304 while (pktType != RTCPUtility::kRtcpNotValidCode)
305 {
306 // Each "case" is responsible for iterate the parser to the
307 // next top level packet.
308 switch (pktType)
309 {
310 case RTCPUtility::kRtcpSrCode:
311 case RTCPUtility::kRtcpRrCode:
312 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
313 break;
314 case RTCPUtility::kRtcpSdesCode:
315 HandleSDES(*rtcpParser);
316 break;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000317 case RTCPUtility::kRtcpXrHeaderCode:
318 HandleXrHeader(*rtcpParser, rtcpPacketInformation);
319 break;
320 case RTCPUtility::kRtcpXrReceiverReferenceTimeCode:
321 HandleXrReceiveReferenceTime(*rtcpParser, rtcpPacketInformation);
322 break;
323 case RTCPUtility::kRtcpXrDlrrReportBlockCode:
324 HandleXrDlrrReportBlock(*rtcpParser, rtcpPacketInformation);
325 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000326 case RTCPUtility::kRtcpXrVoipMetricCode:
327 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
328 break;
329 case RTCPUtility::kRtcpByeCode:
330 HandleBYE(*rtcpParser);
331 break;
332 case RTCPUtility::kRtcpRtpfbNackCode:
333 HandleNACK(*rtcpParser, rtcpPacketInformation);
334 break;
335 case RTCPUtility::kRtcpRtpfbTmmbrCode:
336 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
337 break;
338 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000339 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000340 break;
341 case RTCPUtility::kRtcpRtpfbSrReqCode:
342 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
343 break;
344 case RTCPUtility::kRtcpPsfbPliCode:
345 HandlePLI(*rtcpParser, rtcpPacketInformation);
346 break;
347 case RTCPUtility::kRtcpPsfbSliCode:
348 HandleSLI(*rtcpParser, rtcpPacketInformation);
349 break;
350 case RTCPUtility::kRtcpPsfbRpsiCode:
351 HandleRPSI(*rtcpParser, rtcpPacketInformation);
352 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000353 case RTCPUtility::kRtcpExtendedIjCode:
354 HandleIJ(*rtcpParser, rtcpPacketInformation);
355 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000356 case RTCPUtility::kRtcpPsfbFirCode:
357 HandleFIR(*rtcpParser, rtcpPacketInformation);
358 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000359 case RTCPUtility::kRtcpPsfbAppCode:
360 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
361 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000362 case RTCPUtility::kRtcpAppCode:
363 // generic application messages
364 HandleAPP(*rtcpParser, rtcpPacketInformation);
365 break;
366 case RTCPUtility::kRtcpAppItemCode:
367 // generic application messages
368 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
369 break;
370 default:
371 rtcpParser->Iterate();
372 break;
373 }
374 pktType = rtcpParser->PacketType();
375 }
376 return 0;
377}
378
379// no need for critsect we have _criticalSectionRTCPReceiver
380void
381RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
382 RTCPPacketInformation& rtcpPacketInformation)
383{
384 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
385 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
386
387 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
388
389 // SR.SenderSSRC
390 // The synchronization source identifier for the originator of this SR packet
391
392 // rtcpPacket.RR.SenderSSRC
393 // The source of the packet sender, same as of SR? or is this a CE?
394
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000395 const uint32_t remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
396 const uint8_t numberOfReportBlocks = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.NumberOfReportBlocks:rtcpPacket.SR.NumberOfReportBlocks;
niklase@google.com470e71d2011-07-07 08:21:25 +0000397
398 rtcpPacketInformation.remoteSSRC = remoteSSRC;
399
400 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
401 if (!ptrReceiveInfo)
402 {
403 rtcpParser.Iterate();
404 return;
405 }
406
407 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
408 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000409 TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
410 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000411 "ssrc", main_ssrc_);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000412
niklase@google.com470e71d2011-07-07 08:21:25 +0000413 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
414 {
415 // only signal that we have received a SR when we accept one
416 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
417
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000418 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
419 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
420 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
421
niklase@google.com470e71d2011-07-07 08:21:25 +0000422 // We will only store the send report from one source, but
423 // we will store all the receive block
424
425 // Save the NTP time of this report
426 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
427 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
428 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
429 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
430 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
431
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000432 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000433 }
434 else
435 {
436 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
437 }
438 } else
439 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000440 TRACE_EVENT_INSTANT2("webrtc_rtp", "RR",
441 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000442 "ssrc", main_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000443
444 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
445 }
446 UpdateReceiveInformation(*ptrReceiveInfo);
447
448 rtcpPacketType = rtcpParser.Iterate();
449
450 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
451 {
452 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC, numberOfReportBlocks);
453 rtcpPacketType = rtcpParser.Iterate();
454 }
455}
456
457// no need for critsect we have _criticalSectionRTCPReceiver
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000458void RTCPReceiver::HandleReportBlock(
459 const RTCPUtility::RTCPPacket& rtcpPacket,
460 RTCPPacketInformation& rtcpPacketInformation,
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000461 uint32_t remoteSSRC,
462 uint8_t numberOfReportBlocks)
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000463 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000464 // This will be called once per report block in the RTCP packet.
465 // We filter out all report blocks that are not for us.
466 // Each packet has max 31 RR blocks.
467 //
468 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000469
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000470 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
471 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000472
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000473 // Filter out all report blocks that are not for us.
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000474 if (registered_ssrcs_.find(rtcpPacket.ReportBlockItem.SSRC) ==
475 registered_ssrcs_.end()) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000476 // This block is not for us ignore it.
477 return;
478 }
479
480 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
481 // _criticalSectionRTCPReceiver.
482 _criticalSectionRTCPReceiver->Leave();
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000483 uint32_t sendTimeMS =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000484 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
485 _criticalSectionRTCPReceiver->Enter();
486
487 RTCPReportBlockInformation* reportBlock =
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000488 CreateOrGetReportBlockInformation(remoteSSRC,
489 rtcpPacket.ReportBlockItem.SSRC);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000490 if (reportBlock == NULL) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000491 LOG(LS_WARNING) << "Failed to CreateReportBlockInformation("
492 << remoteSSRC << ")";
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000493 return;
494 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000495
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000496 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000497 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
498 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
499 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
500 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
501 reportBlock->remoteReceiveBlock.cumulativeLost =
502 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000503 if (rb.ExtendedHighestSequenceNumber >
504 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
505 // We have successfully delivered new RTP packets to the remote side after
506 // the last RR was sent from the remote side.
507 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000508 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000509 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
510 rb.ExtendedHighestSequenceNumber;
511 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
512 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
513 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
514
515 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
516 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
517 }
518
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000519 uint32_t delaySinceLastSendReport =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000520 rtcpPacket.ReportBlockItem.DelayLastSR;
521
522 // local NTP time when we received this
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000523 uint32_t lastReceivedRRNTPsecs = 0;
524 uint32_t lastReceivedRRNTPfrac = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000525
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000526 _clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000527
528 // time when we received this in MS
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000529 uint32_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
530 lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000531
532 // Estimate RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000533 uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000534 d /= 65536;
535 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
536
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000537 int32_t RTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000538
539 if (sendTimeMS > 0) {
540 RTT = receiveTimeMS - d - sendTimeMS;
541 if (RTT <= 0) {
542 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000543 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000544 if (RTT > reportBlock->maxRTT) {
545 // store max RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000546 reportBlock->maxRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000547 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000548 if (reportBlock->minRTT == 0) {
549 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000550 reportBlock->minRTT = (uint16_t) RTT;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000551 } else if (RTT < reportBlock->minRTT) {
552 // Store min RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000553 reportBlock->minRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000554 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000555 // store last RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000556 reportBlock->RTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000557
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000558 // store average RTT
559 if (reportBlock->numAverageCalcs != 0) {
560 float ac = static_cast<float> (reportBlock->numAverageCalcs);
561 float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT)
562 + ((1 / (ac + 1)) * RTT);
563 reportBlock->avgRTT = static_cast<int> (newAverage + 0.5f);
564 } else {
565 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000566 reportBlock->avgRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000567 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000568 reportBlock->numAverageCalcs++;
569 }
570
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000571 TRACE_COUNTER_ID1("webrtc_rtp", "RR_RTT", rb.SSRC, RTT);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000572
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000573 rtcpPacketInformation.AddReportInfo(*reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000574}
575
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000576RTCPReportBlockInformation* RTCPReceiver::CreateOrGetReportBlockInformation(
577 uint32_t remote_ssrc,
578 uint32_t source_ssrc) {
579 ReportBlockMap::iterator it = _receivedReportBlockMap.find(source_ssrc);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000580 if (it != _receivedReportBlockMap.end()) {
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000581 ReportBlockInfoMap* info_map = &(it->second);
582 ReportBlockInfoMap::iterator it_info = info_map->find(remote_ssrc);
583 if (it_info != info_map->end()) {
584 return it_info->second;
585 }
586 RTCPReportBlockInformation* info = new RTCPReportBlockInformation;
587 (*info_map)[remote_ssrc] = info;
588 return info;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000589 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000590 RTCPReportBlockInformation* info = new RTCPReportBlockInformation;
591 _receivedReportBlockMap[source_ssrc][remote_ssrc] = info;
592 return info;
niklase@google.com470e71d2011-07-07 08:21:25 +0000593}
594
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000595RTCPReportBlockInformation* RTCPReceiver::GetReportBlockInformation(
596 uint32_t remote_ssrc,
597 uint32_t source_ssrc) const {
598 ReportBlockMap::const_iterator it = _receivedReportBlockMap.find(source_ssrc);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000599 if (it == _receivedReportBlockMap.end()) {
600 return NULL;
601 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000602 const ReportBlockInfoMap* info_map = &(it->second);
603 ReportBlockInfoMap::const_iterator it_info = info_map->find(remote_ssrc);
604 if (it_info == info_map->end()) {
605 return NULL;
606 }
607 return it_info->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000608}
609
610RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000611RTCPReceiver::CreateCnameInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000612 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000613
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000614 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000615 _receivedCnameMap.find(remoteSSRC);
616
617 if (it != _receivedCnameMap.end()) {
618 return it->second;
619 }
620 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000621 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000622 _receivedCnameMap[remoteSSRC] = cnameInfo;
623 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000624}
625
626RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000627RTCPReceiver::GetCnameInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000628 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000629
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000630 std::map<uint32_t, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000631 _receivedCnameMap.find(remoteSSRC);
632
633 if (it == _receivedCnameMap.end()) {
634 return NULL;
635 }
636 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000637}
638
639RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000640RTCPReceiver::CreateReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000641 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000642
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000643 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000644 _receivedInfoMap.find(remoteSSRC);
645
646 if (it != _receivedInfoMap.end()) {
647 return it->second;
648 }
649 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
650 _receivedInfoMap[remoteSSRC] = receiveInfo;
651 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000652}
653
654RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000655RTCPReceiver::GetReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000656 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000657
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000658 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000659 _receivedInfoMap.find(remoteSSRC);
660 if (it == _receivedInfoMap.end()) {
661 return NULL;
662 }
663 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000664}
665
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000666void RTCPReceiver::UpdateReceiveInformation(
667 RTCPReceiveInformation& receiveInformation) {
668 // Update that this remote is alive
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000669 receiveInformation.lastTimeReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000670}
671
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000672bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
673 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
674 if (_lastReceivedRrMs == 0)
675 return false;
676
677 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000678 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000679 // Reset the timer to only trigger one log.
680 _lastReceivedRrMs = 0;
681 return true;
682 }
683 return false;
684}
685
686bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
687 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
688 if (_lastIncreasedSequenceNumberMs == 0)
689 return false;
690
691 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000692 if (_clock->TimeInMilliseconds() > _lastIncreasedSequenceNumberMs +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000693 time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000694 // Reset the timer to only trigger one log.
695 _lastIncreasedSequenceNumberMs = 0;
696 return true;
697 }
698 return false;
699}
700
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000701bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
702 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000703
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000704 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000705 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000706
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000707 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000708 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000709
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000710 while (receiveInfoIt != _receivedInfoMap.end()) {
711 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
712 if (receiveInfo == NULL) {
713 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000714 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000715 // time since last received rtcp packet
716 // when we dont have a lastTimeReceived and the object is marked
717 // readyForDelete it's removed from the map
718 if (receiveInfo->lastTimeReceived) {
719 /// use audio define since we don't know what interval the remote peer is
720 // using
721 if ((timeNow - receiveInfo->lastTimeReceived) >
722 5 * RTCP_INTERVAL_AUDIO_MS) {
723 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000724 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000725 // prevent that we call this over and over again
726 receiveInfo->lastTimeReceived = 0;
727 // send new TMMBN to all channels using the default codec
728 updateBoundingSet = true;
729 }
730 receiveInfoIt++;
731 } else if (receiveInfo->readyForDelete) {
732 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000733 std::map<uint32_t, RTCPReceiveInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000734 receiveInfoItemToBeErased = receiveInfoIt;
735 receiveInfoIt++;
736 delete receiveInfoItemToBeErased->second;
737 _receivedInfoMap.erase(receiveInfoItemToBeErased);
738 } else {
739 receiveInfoIt++;
740 }
741 }
742 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000743}
744
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000745int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000746 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000747
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000748 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000749 _receivedInfoMap.find(_remoteSSRC);
750
751 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000752 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000753 }
754 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
755 if (receiveInfo == NULL) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000756 return -1;
757 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000758 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000759 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000760 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000761 for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000762 i++) {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000763 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000764 // owner of bounding set
765 tmmbrOwner = true;
766 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000767 boundingSetRec->SetEntry(i,
768 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
769 receiveInfo->TmmbnBoundingSet.PacketOH(i),
770 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000771 }
772 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000773 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000774}
775
776// no need for critsect we have _criticalSectionRTCPReceiver
777void
778RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser)
779{
780 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
781 while (pktType == RTCPUtility::kRtcpSdesChunkCode)
782 {
783 HandleSDESChunk(rtcpParser);
784 pktType = rtcpParser.Iterate();
785 }
786}
787
788// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000789void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
790 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
791 RTCPCnameInformation* cnameInfo =
792 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
793 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000794
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000795 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
796 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000797 if (stats_callback_ != NULL) {
798 stats_callback_->CNameChanged(rtcpPacket.CName.CName,
799 rtcpPacket.CName.SenderSSRC);
800 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000801}
802
803// no need for critsect we have _criticalSectionRTCPReceiver
804void
805RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
806 RTCPPacketInformation& rtcpPacketInformation)
807{
808 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000809 if (main_ssrc_ != rtcpPacket.NACK.MediaSSRC)
niklase@google.com470e71d2011-07-07 08:21:25 +0000810 {
811 // Not to us.
812 rtcpParser.Iterate();
813 return;
814 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000815 rtcpPacketInformation.ResetNACKPacketIdArray();
816
817 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
818 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode)
819 {
820 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
821 pktType = rtcpParser.Iterate();
822 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000823
824 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
825 ++packet_type_counter_.nack_packets;
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000826 packet_type_counter_.nack_requests = nack_stats_.requests();
827 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000828 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000829}
830
831// no need for critsect we have _criticalSectionRTCPReceiver
832void
833RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
834 RTCPPacketInformation& rtcpPacketInformation)
835{
836 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000837 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000838
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000839 uint16_t bitMask = rtcpPacket.NACKItem.BitMask;
niklase@google.com470e71d2011-07-07 08:21:25 +0000840 if(bitMask)
841 {
842 for(int i=1; i <= 16; ++i)
843 {
844 if(bitMask & 0x01)
845 {
846 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000847 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID + i);
niklase@google.com470e71d2011-07-07 08:21:25 +0000848 }
849 bitMask = bitMask >>1;
850 }
851 }
852
853 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
854}
855
856// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000857void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
858 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000859
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000860 // clear our lists
861 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000862 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
863 for (; it != _receivedReportBlockMap.end(); ++it) {
864 ReportBlockInfoMap* info_map = &(it->second);
865 ReportBlockInfoMap::iterator it_info = info_map->find(
866 rtcpPacket.BYE.SenderSSRC);
867 if (it_info != info_map->end()) {
868 delete it_info->second;
869 info_map->erase(it_info);
870 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000871 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000872
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000873 // we can't delete it due to TMMBR
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000874 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000875 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000876
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000877 if (receiveInfoIt != _receivedInfoMap.end()) {
878 receiveInfoIt->second->readyForDelete = true;
879 }
880
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000881 std::map<uint32_t, RTCPCnameInformation*>::iterator cnameInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000882 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
883
884 if (cnameInfoIt != _receivedCnameMap.end()) {
885 delete cnameInfoIt->second;
886 _receivedCnameMap.erase(cnameInfoIt);
887 }
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000888 xr_rr_rtt_ms_ = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000889 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000890}
891
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000892void RTCPReceiver::HandleXrHeader(
893 RTCPUtility::RTCPParserV2& parser,
894 RTCPPacketInformation& rtcpPacketInformation) {
895 const RTCPUtility::RTCPPacket& packet = parser.Packet();
896
897 rtcpPacketInformation.xr_originator_ssrc = packet.XR.OriginatorSSRC;
898
899 parser.Iterate();
900}
901
902void RTCPReceiver::HandleXrReceiveReferenceTime(
903 RTCPUtility::RTCPParserV2& parser,
904 RTCPPacketInformation& rtcpPacketInformation) {
905 const RTCPUtility::RTCPPacket& packet = parser.Packet();
906
907 _remoteXRReceiveTimeInfo.sourceSSRC =
908 rtcpPacketInformation.xr_originator_ssrc;
909
910 _remoteXRReceiveTimeInfo.lastRR = RTCPUtility::MidNtp(
911 packet.XRReceiverReferenceTimeItem.NTPMostSignificant,
912 packet.XRReceiverReferenceTimeItem.NTPLeastSignificant);
913
914 _clock->CurrentNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);
915
916 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
917
918 parser.Iterate();
919}
920
921void RTCPReceiver::HandleXrDlrrReportBlock(
922 RTCPUtility::RTCPParserV2& parser,
923 RTCPPacketInformation& rtcpPacketInformation) {
924 const RTCPUtility::RTCPPacket& packet = parser.Packet();
925 // Iterate through sub-block(s), if any.
926 RTCPUtility::RTCPPacketTypes packet_type = parser.Iterate();
927
928 while (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
929 HandleXrDlrrReportBlockItem(packet, rtcpPacketInformation);
930 packet_type = parser.Iterate();
931 }
932}
933
934void RTCPReceiver::HandleXrDlrrReportBlockItem(
935 const RTCPUtility::RTCPPacket& packet,
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000936 RTCPPacketInformation& rtcpPacketInformation)
937 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000938 if (registered_ssrcs_.find(packet.XRDLRRReportBlockItem.SSRC) ==
939 registered_ssrcs_.end()) {
940 // Not to us.
941 return;
942 }
943
944 rtcpPacketInformation.xr_dlrr_item = true;
945
946 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
947 // _criticalSectionRTCPReceiver.
948 _criticalSectionRTCPReceiver->Leave();
949
950 int64_t send_time_ms;
951 bool found = _rtpRtcp.SendTimeOfXrRrReport(
952 packet.XRDLRRReportBlockItem.LastRR, &send_time_ms);
953
954 _criticalSectionRTCPReceiver->Enter();
955
956 if (!found) {
957 return;
958 }
959
960 // The DelayLastRR field is in units of 1/65536 sec.
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000961 uint32_t delay_rr_ms =
962 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0x0000ffff) * 1000) >> 16) +
963 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0xffff0000) >> 16) * 1000);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000964
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000965 int32_t rtt = _clock->CurrentNtpInMilliseconds() - delay_rr_ms - send_time_ms;
966
967 xr_rr_rtt_ms_ = static_cast<uint16_t>(std::max(rtt, 1));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000968
969 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
970}
971
niklase@google.com470e71d2011-07-07 08:21:25 +0000972// no need for critsect we have _criticalSectionRTCPReceiver
973void
974RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
975 RTCPPacketInformation& rtcpPacketInformation)
976{
977 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
978
979 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
980
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000981 if(rtcpPacket.XRVOIPMetricItem.SSRC == main_ssrc_)
niklase@google.com470e71d2011-07-07 08:21:25 +0000982 {
983 // Store VoIP metrics block if it's about me
984 // from OriginatorSSRC do we filter it?
985 // rtcpPacket.XR.OriginatorSSRC;
986
987 RTCPVoIPMetric receivedVoIPMetrics;
988 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
989 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
990 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
991 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
992 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
993 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
994 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
995 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
996 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
997 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
998 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
999 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
1000 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
1001 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
1002 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
1003 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
1004 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
1005 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
1006 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
1007 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
1008
1009 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
1010
1011 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
1012 }
1013 rtcpParser.Iterate();
1014}
1015
1016// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001017void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
1018 RTCPPacketInformation& rtcpPacketInformation) {
1019 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001020 if (main_ssrc_ == rtcpPacket.PLI.MediaSSRC) {
justinlin@chromium.org7bfb3a32013-05-13 22:59:00 +00001021 TRACE_EVENT_INSTANT0("webrtc_rtp", "PLI");
1022
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001023 ++packet_type_counter_.pli_packets;
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001024 // Received a signal that we need to send a new key frame.
1025 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
1026 }
1027 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001028}
1029
1030// no need for critsect we have _criticalSectionRTCPReceiver
1031void
1032RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
1033 RTCPPacketInformation& rtcpPacketInformation)
1034{
1035 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1036
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001037 uint32_t senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001038 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
1039 if (ptrReceiveInfo == NULL)
1040 {
1041 // This remote SSRC must be saved before.
1042 rtcpParser.Iterate();
1043 return;
1044 }
1045 if(rtcpPacket.TMMBR.MediaSSRC)
1046 {
1047 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
1048 // in relay mode this is a valid number
1049 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
1050 }
1051
1052 // Use packet length to calc max number of TMMBR blocks
1053 // each TMMBR block is 8 bytes
1054 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
1055
1056 // sanity
1057 if(maxNumOfTMMBRBlocks > 200) // we can't have more than what's in one packet
1058 {
1059 assert(false);
1060 rtcpParser.Iterate();
1061 return;
1062 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001063 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((uint32_t)maxNumOfTMMBRBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001064
1065 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1066 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode)
1067 {
1068 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
1069 pktType = rtcpParser.Iterate();
1070 }
1071}
1072
1073// no need for critsect we have _criticalSectionRTCPReceiver
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001074void RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
1075 const RTCPUtility::RTCPPacket& rtcpPacket,
1076 RTCPPacketInformation& rtcpPacketInformation,
1077 uint32_t senderSSRC) {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001078 if (main_ssrc_ == rtcpPacket.TMMBRItem.SSRC &&
niklase@google.com470e71d2011-07-07 08:21:25 +00001079 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
1080 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001081 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001082 _clock->TimeInMilliseconds());
niklase@google.com470e71d2011-07-07 08:21:25 +00001083 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
1084 }
1085}
1086
1087// no need for critsect we have _criticalSectionRTCPReceiver
1088void
hta@webrtc.org9d54cd12012-04-30 08:24:55 +00001089RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
1090 RTCPPacketInformation& rtcpPacketInformation)
niklase@google.com470e71d2011-07-07 08:21:25 +00001091{
1092 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1093 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.TMMBN.SenderSSRC);
1094 if (ptrReceiveInfo == NULL)
1095 {
1096 // This remote SSRC must be saved before.
1097 rtcpParser.Iterate();
1098 return;
1099 }
hta@webrtc.org9d54cd12012-04-30 08:24:55 +00001100 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +00001101 // Use packet length to calc max number of TMMBN blocks
1102 // each TMMBN block is 8 bytes
1103 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
1104
1105 // sanity
1106 if(maxNumOfTMMBNBlocks > 200) // we cant have more than what's in one packet
1107 {
1108 assert(false);
1109 rtcpParser.Iterate();
1110 return;
1111 }
1112
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001113 ptrReceiveInfo->VerifyAndAllocateBoundingSet((uint32_t)maxNumOfTMMBNBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001114
1115 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1116 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode)
1117 {
1118 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
1119 pktType = rtcpParser.Iterate();
1120 }
1121}
1122
1123// no need for critsect we have _criticalSectionRTCPReceiver
1124void
1125RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
1126 RTCPPacketInformation& rtcpPacketInformation)
1127{
1128 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
1129 rtcpParser.Iterate();
1130}
1131
1132// no need for critsect we have _criticalSectionRTCPReceiver
1133void
1134RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
1135 const RTCPUtility::RTCPPacket& rtcpPacket)
1136{
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001137 receiveInfo.TmmbnBoundingSet.AddEntry(
1138 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
1139 rtcpPacket.TMMBNItem.MeasuredOverhead,
1140 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001141}
1142
1143// no need for critsect we have _criticalSectionRTCPReceiver
1144void
1145RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
1146 RTCPPacketInformation& rtcpPacketInformation)
1147{
1148 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001149 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1150 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode)
1151 {
1152 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1153 pktType = rtcpParser.Iterate();
1154 }
1155}
1156
1157// no need for critsect we have _criticalSectionRTCPReceiver
1158void
1159RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1160 RTCPPacketInformation& rtcpPacketInformation)
1161{
1162 // in theory there could be multiple slices lost
1163 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1164 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
1165}
1166
1167void
1168RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1169 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1170{
1171 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001172 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1173 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1174 {
1175 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1176 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1177 {
1178 // to us unknown
1179 // continue
1180 rtcpParser.Iterate();
1181 return;
1182 }
1183 rtcpPacketInformation.rpsiPictureId = 0;
1184
1185 // convert NativeBitString to rpsiPictureId
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001186 uint8_t numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1187 for(uint8_t n = 0; n < (numberOfBytes-1); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001188 {
1189 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1190 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1191 }
1192 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1193 }
1194}
1195
1196// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001197void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1198 RTCPPacketInformation& rtcpPacketInformation) {
1199 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1200 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1201 pktType = rtcpParser.Iterate();
1202 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1203 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1204 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001205 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001206 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001207}
1208
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001209// no need for critsect we have _criticalSectionRTCPReceiver
1210void
1211RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1212 RTCPPacketInformation& rtcpPacketInformation)
1213{
1214 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1215
1216 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1217 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode)
1218 {
1219 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1220 pktType = rtcpParser.Iterate();
1221 }
1222}
1223
1224void
1225RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1226 RTCPPacketInformation& rtcpPacketInformation)
1227{
1228 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1229 rtcpPacketInformation.interArrivalJitter =
1230 rtcpPacket.ExtendedJitterReportItem.Jitter;
1231}
1232
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001233void RTCPReceiver::HandleREMBItem(
1234 RTCPUtility::RTCPParserV2& rtcpParser,
1235 RTCPPacketInformation& rtcpPacketInformation) {
1236 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1237 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1238 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1239 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001240}
1241
1242// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001243void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1244 RTCPPacketInformation& rtcpPacketInformation) {
1245 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1246 RTCPReceiveInformation* ptrReceiveInfo =
1247 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001248
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001249 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1250 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1251 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1252 pktType = rtcpParser.Iterate();
1253 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001254}
1255
1256// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001257void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1258 const RTCPUtility::RTCPPacket& rtcpPacket,
1259 RTCPPacketInformation& rtcpPacketInformation) {
1260 // Is it our sender that is requested to generate a new keyframe
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001261 if (main_ssrc_ != rtcpPacket.FIRItem.SSRC) {
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001262 return;
1263 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001264
1265 ++packet_type_counter_.fir_packets;
1266
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001267 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1268 // we don't know who this originate from
1269 if (receiveInfo) {
1270 // check if we have reported this FIRSequenceNumber before
1271 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1272 receiveInfo->lastFIRSequenceNumber) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001273 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001274 // sanity; don't go crazy with the callbacks
1275 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1276 receiveInfo->lastFIRRequest = now;
1277 receiveInfo->lastFIRSequenceNumber =
1278 rtcpPacket.FIRItem.CommandSequenceNumber;
1279 // received signal that we need to send a new key frame
1280 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1281 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001282 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001283 } else {
1284 // received signal that we need to send a new key frame
1285 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1286 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001287}
1288
1289void
1290RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1291 RTCPPacketInformation& rtcpPacketInformation)
1292{
1293 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1294
1295 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1296 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1297 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
1298
1299 rtcpParser.Iterate();
1300}
1301
1302void
1303RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1304 RTCPPacketInformation& rtcpPacketInformation)
1305{
1306 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1307
1308 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
1309
1310 rtcpParser.Iterate();
1311}
1312
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001313int32_t RTCPReceiver::UpdateTMMBR() {
1314 int32_t numBoundingSet = 0;
1315 uint32_t bitrate = 0;
1316 uint32_t accNumCandidates = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001317
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001318 int32_t size = TMMBRReceived(0, 0, NULL);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001319 if (size > 0) {
1320 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1321 // Get candidate set from receiver.
1322 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1323 } else {
1324 // Candidate set empty.
1325 VerifyAndAllocateCandidateSet(0); // resets candidate set
1326 }
1327 // Find bounding set
1328 TMMBRSet* boundingSet = NULL;
1329 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1330 if (numBoundingSet == -1) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001331 LOG(LS_WARNING) << "Failed to find TMMBR bounding set.";
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001332 return -1;
1333 }
1334 // Set bounding set
1335 // Inform remote clients about the new bandwidth
1336 // inform the remote client
1337 _rtpRtcp.SetTMMBN(boundingSet);
1338
1339 // might trigger a TMMBN
1340 if (numBoundingSet == 0) {
1341 // owner of max bitrate request has timed out
1342 // empty bounding set has been sent
1343 return 0;
1344 }
1345 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001346 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001347 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001348 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1349 if (_cbRtcpBandwidthObserver) {
1350 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001351 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001352 }
1353 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001354}
1355
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001356void RTCPReceiver::RegisterRtcpStatisticsCallback(
1357 RtcpStatisticsCallback* callback) {
1358 CriticalSectionScoped cs(_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001359 stats_callback_ = callback;
1360}
1361
1362RtcpStatisticsCallback* RTCPReceiver::GetRtcpStatisticsCallback() {
1363 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1364 return stats_callback_;
1365}
1366
niklase@google.com470e71d2011-07-07 08:21:25 +00001367// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001368void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001369 RTCPPacketInformation& rtcpPacketInformation) {
1370 // Process TMMBR and REMB first to avoid multiple callbacks
1371 // to OnNetworkChanged.
1372 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001373 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1374 UpdateTMMBR();
1375 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001376 unsigned int local_ssrc = 0;
1377 {
1378 // We don't want to hold this critsect when triggering the callbacks below.
1379 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001380 local_ssrc = main_ssrc_;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001381 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001382 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1383 _rtpRtcp.OnRequestSendReport();
1384 }
1385 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001386 if (rtcpPacketInformation.nackSequenceNumbers.size() > 0) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001387 LOG(LS_VERBOSE) << "Incoming NACK length: "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001388 << rtcpPacketInformation.nackSequenceNumbers.size();
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001389 _rtpRtcp.OnReceivedNACK(rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001390 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001391 }
1392 {
1393 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001394
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001395 // We need feedback that we have received a report block(s) so that we
1396 // can generate a new packet in a conference relay scenario, one received
1397 // report can generate several RTCP packets, based on number relayed/mixed
1398 // a send report block should go out to all receivers.
1399 if (_cbRtcpIntraFrameObserver) {
1400 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1401 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1402 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001403 LOG(LS_VERBOSE) << "Incoming PLI from SSRC "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001404 << rtcpPacketInformation.remoteSSRC;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001405 } else {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001406 LOG(LS_VERBOSE) << "Incoming FIR from SSRC "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001407 << rtcpPacketInformation.remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001408 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001409 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001410 }
1411 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1412 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001413 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001414 }
1415 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1416 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001417 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001418 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001419 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001420 if (_cbRtcpBandwidthObserver) {
1421 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001422 LOG(LS_VERBOSE) << "Incoming REMB: "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001423 << rtcpPacketInformation.receiverEstimatedMaxBitrate;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001424 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1425 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1426 }
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001427 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1428 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001429 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001430 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001431 rtcpPacketInformation.report_blocks,
1432 rtcpPacketInformation.rtt,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001433 now);
1434 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001435 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001436 }
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001437
1438 {
1439 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1440 if (stats_callback_) {
1441 for (ReportBlockList::const_iterator it =
1442 rtcpPacketInformation.report_blocks.begin();
1443 it != rtcpPacketInformation.report_blocks.end();
1444 ++it) {
1445 RtcpStatistics stats;
1446 stats.cumulative_lost = it->cumulativeLost;
1447 stats.extended_max_sequence_number = it->extendedHighSeqNum;
1448 stats.fraction_lost = it->fractionLost;
1449 stats.jitter = it->jitter;
1450
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001451 stats_callback_->StatisticsUpdated(stats, it->sourceSSRC);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001452 }
1453 }
1454 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001455}
1456
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001457int32_t RTCPReceiver::CNAME(uint32_t remoteSSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001458 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001459 assert(cName);
1460
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001461 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1462 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001463 if (cnameInfo == NULL) {
1464 return -1;
1465 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001466 cName[RTCP_CNAME_SIZE - 1] = 0;
1467 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1468 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001469}
1470
1471// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001472int32_t RTCPReceiver::TMMBRReceived(uint32_t size,
1473 uint32_t accNumCandidates,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001474 TMMBRSet* candidateSet) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001475 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001476
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001477 std::map<uint32_t, RTCPReceiveInformation*>::const_iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001478 receiveInfoIt = _receivedInfoMap.begin();
1479 if (receiveInfoIt == _receivedInfoMap.end()) {
1480 return -1;
1481 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001482 uint32_t num = accNumCandidates;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001483 if (candidateSet) {
1484 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1485 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1486 if (receiveInfo == NULL) {
1487 return 0;
1488 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001489 for (uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001490 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001491 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001492 _clock->TimeInMilliseconds()) == 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001493 num++;
1494 }
1495 }
1496 receiveInfoIt++;
1497 }
1498 } else {
1499 while (receiveInfoIt != _receivedInfoMap.end()) {
1500 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1501 if(receiveInfo == NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001502 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001503 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001504 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001505 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001506 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001507 }
1508 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001509}
1510
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001511} // namespace webrtc