blob: 4012a81cd541d745e628099d5ecc9c8a80507045 [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
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000320void RTCPReceiver::GetPacketTypeCounter(
321 RtcpPacketTypeCounter* packet_counter) const {
322 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
323 *packet_counter = packet_type_counter_;
324}
325
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000326int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000327RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
328 RTCPUtility::RTCPParserV2* rtcpParser)
329{
330 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
331
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000332 _lastReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000333
334 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
335 while (pktType != RTCPUtility::kRtcpNotValidCode)
336 {
337 // Each "case" is responsible for iterate the parser to the
338 // next top level packet.
339 switch (pktType)
340 {
341 case RTCPUtility::kRtcpSrCode:
342 case RTCPUtility::kRtcpRrCode:
343 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
344 break;
345 case RTCPUtility::kRtcpSdesCode:
346 HandleSDES(*rtcpParser);
347 break;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000348 case RTCPUtility::kRtcpXrHeaderCode:
349 HandleXrHeader(*rtcpParser, rtcpPacketInformation);
350 break;
351 case RTCPUtility::kRtcpXrReceiverReferenceTimeCode:
352 HandleXrReceiveReferenceTime(*rtcpParser, rtcpPacketInformation);
353 break;
354 case RTCPUtility::kRtcpXrDlrrReportBlockCode:
355 HandleXrDlrrReportBlock(*rtcpParser, rtcpPacketInformation);
356 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000357 case RTCPUtility::kRtcpXrVoipMetricCode:
358 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
359 break;
360 case RTCPUtility::kRtcpByeCode:
361 HandleBYE(*rtcpParser);
362 break;
363 case RTCPUtility::kRtcpRtpfbNackCode:
364 HandleNACK(*rtcpParser, rtcpPacketInformation);
365 break;
366 case RTCPUtility::kRtcpRtpfbTmmbrCode:
367 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
368 break;
369 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000370 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000371 break;
372 case RTCPUtility::kRtcpRtpfbSrReqCode:
373 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
374 break;
375 case RTCPUtility::kRtcpPsfbPliCode:
376 HandlePLI(*rtcpParser, rtcpPacketInformation);
377 break;
378 case RTCPUtility::kRtcpPsfbSliCode:
379 HandleSLI(*rtcpParser, rtcpPacketInformation);
380 break;
381 case RTCPUtility::kRtcpPsfbRpsiCode:
382 HandleRPSI(*rtcpParser, rtcpPacketInformation);
383 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000384 case RTCPUtility::kRtcpExtendedIjCode:
385 HandleIJ(*rtcpParser, rtcpPacketInformation);
386 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000387 case RTCPUtility::kRtcpPsfbFirCode:
388 HandleFIR(*rtcpParser, rtcpPacketInformation);
389 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000390 case RTCPUtility::kRtcpPsfbAppCode:
391 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
392 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000393 case RTCPUtility::kRtcpAppCode:
394 // generic application messages
395 HandleAPP(*rtcpParser, rtcpPacketInformation);
396 break;
397 case RTCPUtility::kRtcpAppItemCode:
398 // generic application messages
399 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
400 break;
401 default:
402 rtcpParser->Iterate();
403 break;
404 }
405 pktType = rtcpParser->PacketType();
406 }
407 return 0;
408}
409
410// no need for critsect we have _criticalSectionRTCPReceiver
411void
412RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
413 RTCPPacketInformation& rtcpPacketInformation)
414{
415 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
416 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
417
418 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
419
420 // SR.SenderSSRC
421 // The synchronization source identifier for the originator of this SR packet
422
423 // rtcpPacket.RR.SenderSSRC
424 // The source of the packet sender, same as of SR? or is this a CE?
425
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000426 const uint32_t remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
427 const uint8_t numberOfReportBlocks = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.NumberOfReportBlocks:rtcpPacket.SR.NumberOfReportBlocks;
niklase@google.com470e71d2011-07-07 08:21:25 +0000428
429 rtcpPacketInformation.remoteSSRC = remoteSSRC;
430
431 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
432 if (!ptrReceiveInfo)
433 {
434 rtcpParser.Iterate();
435 return;
436 }
437
438 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
439 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000440 TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
441 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000442 "ssrc", main_ssrc_);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000443
niklase@google.com470e71d2011-07-07 08:21:25 +0000444 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
445 {
446 // only signal that we have received a SR when we accept one
447 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
448
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000449 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
450 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
451 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
452
niklase@google.com470e71d2011-07-07 08:21:25 +0000453 // We will only store the send report from one source, but
454 // we will store all the receive block
455
456 // Save the NTP time of this report
457 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
458 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
459 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
460 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
461 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
462
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000463 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000464 }
465 else
466 {
467 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
468 }
469 } else
470 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000471 TRACE_EVENT_INSTANT2("webrtc_rtp", "RR",
472 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000473 "ssrc", main_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000474
475 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
476 }
477 UpdateReceiveInformation(*ptrReceiveInfo);
478
479 rtcpPacketType = rtcpParser.Iterate();
480
481 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
482 {
483 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC, numberOfReportBlocks);
484 rtcpPacketType = rtcpParser.Iterate();
485 }
486}
487
488// no need for critsect we have _criticalSectionRTCPReceiver
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000489void RTCPReceiver::HandleReportBlock(
490 const RTCPUtility::RTCPPacket& rtcpPacket,
491 RTCPPacketInformation& rtcpPacketInformation,
492 const uint32_t remoteSSRC,
493 const uint8_t numberOfReportBlocks)
494 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000495 // This will be called once per report block in the RTCP packet.
496 // We filter out all report blocks that are not for us.
497 // Each packet has max 31 RR blocks.
498 //
499 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000500
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000501 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
502 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000503
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000504 // Filter out all report blocks that are not for us.
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000505 if (registered_ssrcs_.find(rtcpPacket.ReportBlockItem.SSRC) ==
506 registered_ssrcs_.end()) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000507 // This block is not for us ignore it.
508 return;
509 }
510
511 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
512 // _criticalSectionRTCPReceiver.
513 _criticalSectionRTCPReceiver->Leave();
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000514 uint32_t sendTimeMS =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000515 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
516 _criticalSectionRTCPReceiver->Enter();
517
518 RTCPReportBlockInformation* reportBlock =
519 CreateReportBlockInformation(remoteSSRC);
520 if (reportBlock == NULL) {
521 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
522 "\tfailed to CreateReportBlockInformation(%u)", remoteSSRC);
523 return;
524 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000525
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000526 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000527 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
528 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
529 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
530 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
531 reportBlock->remoteReceiveBlock.cumulativeLost =
532 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000533 if (rb.ExtendedHighestSequenceNumber >
534 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
535 // We have successfully delivered new RTP packets to the remote side after
536 // the last RR was sent from the remote side.
537 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000538 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000539 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
540 rb.ExtendedHighestSequenceNumber;
541 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
542 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
543 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
544
545 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
546 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
547 }
548
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000549 uint32_t delaySinceLastSendReport =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000550 rtcpPacket.ReportBlockItem.DelayLastSR;
551
552 // local NTP time when we received this
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000553 uint32_t lastReceivedRRNTPsecs = 0;
554 uint32_t lastReceivedRRNTPfrac = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000555
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000556 _clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000557
558 // time when we received this in MS
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000559 uint32_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
560 lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000561
562 // Estimate RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000563 uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000564 d /= 65536;
565 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
566
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000567 int32_t RTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000568
569 if (sendTimeMS > 0) {
570 RTT = receiveTimeMS - d - sendTimeMS;
571 if (RTT <= 0) {
572 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000573 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000574 if (RTT > reportBlock->maxRTT) {
575 // store max RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000576 reportBlock->maxRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000577 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000578 if (reportBlock->minRTT == 0) {
579 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000580 reportBlock->minRTT = (uint16_t) RTT;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000581 } else if (RTT < reportBlock->minRTT) {
582 // Store min RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000583 reportBlock->minRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000584 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000585 // store last RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000586 reportBlock->RTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000587
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000588 // store average RTT
589 if (reportBlock->numAverageCalcs != 0) {
590 float ac = static_cast<float> (reportBlock->numAverageCalcs);
591 float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT)
592 + ((1 / (ac + 1)) * RTT);
593 reportBlock->avgRTT = static_cast<int> (newAverage + 0.5f);
594 } else {
595 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000596 reportBlock->avgRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000597 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000598 reportBlock->numAverageCalcs++;
599 }
600
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000601 TRACE_COUNTER_ID1("webrtc_rtp", "RR_RTT", rb.SSRC, RTT);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000602
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000603 rtcpPacketInformation.AddReportInfo(*reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000604}
605
606RTCPReportBlockInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000607RTCPReceiver::CreateReportBlockInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000608 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000609
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000610 std::map<uint32_t, RTCPReportBlockInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000611 _receivedReportBlockMap.find(remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000612
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000613 RTCPReportBlockInformation* ptrReportBlockInfo = NULL;
614 if (it != _receivedReportBlockMap.end()) {
615 ptrReportBlockInfo = it->second;
616 } else {
617 ptrReportBlockInfo = new RTCPReportBlockInformation;
618 _receivedReportBlockMap[remoteSSRC] = ptrReportBlockInfo;
619 }
620 return ptrReportBlockInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000621}
622
623RTCPReportBlockInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000624RTCPReceiver::GetReportBlockInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000625 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000626
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000627 std::map<uint32_t, RTCPReportBlockInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000628 _receivedReportBlockMap.find(remoteSSRC);
629
630 if (it == _receivedReportBlockMap.end()) {
631 return NULL;
632 }
633 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000634}
635
636RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000637RTCPReceiver::CreateCnameInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000638 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000639
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000640 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000641 _receivedCnameMap.find(remoteSSRC);
642
643 if (it != _receivedCnameMap.end()) {
644 return it->second;
645 }
646 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000647 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000648 _receivedCnameMap[remoteSSRC] = cnameInfo;
649 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000650}
651
652RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000653RTCPReceiver::GetCnameInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000654 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000655
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000656 std::map<uint32_t, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000657 _receivedCnameMap.find(remoteSSRC);
658
659 if (it == _receivedCnameMap.end()) {
660 return NULL;
661 }
662 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000663}
664
665RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000666RTCPReceiver::CreateReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000667 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000668
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000669 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000670 _receivedInfoMap.find(remoteSSRC);
671
672 if (it != _receivedInfoMap.end()) {
673 return it->second;
674 }
675 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
676 _receivedInfoMap[remoteSSRC] = receiveInfo;
677 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000678}
679
680RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000681RTCPReceiver::GetReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000682 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000683
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000684 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000685 _receivedInfoMap.find(remoteSSRC);
686 if (it == _receivedInfoMap.end()) {
687 return NULL;
688 }
689 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000690}
691
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000692void RTCPReceiver::UpdateReceiveInformation(
693 RTCPReceiveInformation& receiveInformation) {
694 // Update that this remote is alive
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000695 receiveInformation.lastTimeReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000696}
697
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000698bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
699 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
700 if (_lastReceivedRrMs == 0)
701 return false;
702
703 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000704 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000705 // Reset the timer to only trigger one log.
706 _lastReceivedRrMs = 0;
707 return true;
708 }
709 return false;
710}
711
712bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
713 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
714 if (_lastIncreasedSequenceNumberMs == 0)
715 return false;
716
717 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000718 if (_clock->TimeInMilliseconds() > _lastIncreasedSequenceNumberMs +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000719 time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000720 // Reset the timer to only trigger one log.
721 _lastIncreasedSequenceNumberMs = 0;
722 return true;
723 }
724 return false;
725}
726
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000727bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
728 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000729
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000730 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000731 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000732
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000733 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000734 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000735
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000736 while (receiveInfoIt != _receivedInfoMap.end()) {
737 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
738 if (receiveInfo == NULL) {
739 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000740 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000741 // time since last received rtcp packet
742 // when we dont have a lastTimeReceived and the object is marked
743 // readyForDelete it's removed from the map
744 if (receiveInfo->lastTimeReceived) {
745 /// use audio define since we don't know what interval the remote peer is
746 // using
747 if ((timeNow - receiveInfo->lastTimeReceived) >
748 5 * RTCP_INTERVAL_AUDIO_MS) {
749 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000750 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000751 // prevent that we call this over and over again
752 receiveInfo->lastTimeReceived = 0;
753 // send new TMMBN to all channels using the default codec
754 updateBoundingSet = true;
755 }
756 receiveInfoIt++;
757 } else if (receiveInfo->readyForDelete) {
758 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000759 std::map<uint32_t, RTCPReceiveInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000760 receiveInfoItemToBeErased = receiveInfoIt;
761 receiveInfoIt++;
762 delete receiveInfoItemToBeErased->second;
763 _receivedInfoMap.erase(receiveInfoItemToBeErased);
764 } else {
765 receiveInfoIt++;
766 }
767 }
768 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000769}
770
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000771int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000772 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000773
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000774 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000775 _receivedInfoMap.find(_remoteSSRC);
776
777 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000778 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000779 }
780 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
781 if (receiveInfo == NULL) {
782 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
783 "%s failed to get RTCPReceiveInformation",
784 __FUNCTION__);
785 return -1;
786 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000787 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000788 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000789 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000790 for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000791 i++) {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000792 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000793 // owner of bounding set
794 tmmbrOwner = true;
795 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000796 boundingSetRec->SetEntry(i,
797 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
798 receiveInfo->TmmbnBoundingSet.PacketOH(i),
799 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000800 }
801 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000802 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000803}
804
805// no need for critsect we have _criticalSectionRTCPReceiver
806void
807RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser)
808{
809 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
810 while (pktType == RTCPUtility::kRtcpSdesChunkCode)
811 {
812 HandleSDESChunk(rtcpParser);
813 pktType = rtcpParser.Iterate();
814 }
815}
816
817// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000818void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
819 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
820 RTCPCnameInformation* cnameInfo =
821 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
822 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000823
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000824 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
825 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000826}
827
828// no need for critsect we have _criticalSectionRTCPReceiver
829void
830RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
831 RTCPPacketInformation& rtcpPacketInformation)
832{
833 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000834 if (main_ssrc_ != rtcpPacket.NACK.MediaSSRC)
niklase@google.com470e71d2011-07-07 08:21:25 +0000835 {
836 // Not to us.
837 rtcpParser.Iterate();
838 return;
839 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000840 rtcpPacketInformation.ResetNACKPacketIdArray();
841
842 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
843 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode)
844 {
845 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
846 pktType = rtcpParser.Iterate();
847 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000848
849 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
850 ++packet_type_counter_.nack_packets;
851 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000852}
853
854// no need for critsect we have _criticalSectionRTCPReceiver
855void
856RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
857 RTCPPacketInformation& rtcpPacketInformation)
858{
859 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
860
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000861 uint16_t bitMask = rtcpPacket.NACKItem.BitMask;
niklase@google.com470e71d2011-07-07 08:21:25 +0000862 if(bitMask)
863 {
864 for(int i=1; i <= 16; ++i)
865 {
866 if(bitMask & 0x01)
867 {
868 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
869 }
870 bitMask = bitMask >>1;
871 }
872 }
873
874 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
875}
876
877// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000878void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
879 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000880
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000881 // clear our lists
882 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000883 std::map<uint32_t, RTCPReportBlockInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000884 reportBlockInfoIt = _receivedReportBlockMap.find(
885 rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000886
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000887 if (reportBlockInfoIt != _receivedReportBlockMap.end()) {
888 delete reportBlockInfoIt->second;
889 _receivedReportBlockMap.erase(reportBlockInfoIt);
890 }
891 // we can't delete it due to TMMBR
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000892 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000893 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000894
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000895 if (receiveInfoIt != _receivedInfoMap.end()) {
896 receiveInfoIt->second->readyForDelete = true;
897 }
898
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000899 std::map<uint32_t, RTCPCnameInformation*>::iterator cnameInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000900 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
901
902 if (cnameInfoIt != _receivedCnameMap.end()) {
903 delete cnameInfoIt->second;
904 _receivedCnameMap.erase(cnameInfoIt);
905 }
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000906 xr_rr_rtt_ms_ = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000907 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000908}
909
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000910void RTCPReceiver::HandleXrHeader(
911 RTCPUtility::RTCPParserV2& parser,
912 RTCPPacketInformation& rtcpPacketInformation) {
913 const RTCPUtility::RTCPPacket& packet = parser.Packet();
914
915 rtcpPacketInformation.xr_originator_ssrc = packet.XR.OriginatorSSRC;
916
917 parser.Iterate();
918}
919
920void RTCPReceiver::HandleXrReceiveReferenceTime(
921 RTCPUtility::RTCPParserV2& parser,
922 RTCPPacketInformation& rtcpPacketInformation) {
923 const RTCPUtility::RTCPPacket& packet = parser.Packet();
924
925 _remoteXRReceiveTimeInfo.sourceSSRC =
926 rtcpPacketInformation.xr_originator_ssrc;
927
928 _remoteXRReceiveTimeInfo.lastRR = RTCPUtility::MidNtp(
929 packet.XRReceiverReferenceTimeItem.NTPMostSignificant,
930 packet.XRReceiverReferenceTimeItem.NTPLeastSignificant);
931
932 _clock->CurrentNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);
933
934 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
935
936 parser.Iterate();
937}
938
939void RTCPReceiver::HandleXrDlrrReportBlock(
940 RTCPUtility::RTCPParserV2& parser,
941 RTCPPacketInformation& rtcpPacketInformation) {
942 const RTCPUtility::RTCPPacket& packet = parser.Packet();
943 // Iterate through sub-block(s), if any.
944 RTCPUtility::RTCPPacketTypes packet_type = parser.Iterate();
945
946 while (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
947 HandleXrDlrrReportBlockItem(packet, rtcpPacketInformation);
948 packet_type = parser.Iterate();
949 }
950}
951
952void RTCPReceiver::HandleXrDlrrReportBlockItem(
953 const RTCPUtility::RTCPPacket& packet,
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000954 RTCPPacketInformation& rtcpPacketInformation)
955 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000956 if (registered_ssrcs_.find(packet.XRDLRRReportBlockItem.SSRC) ==
957 registered_ssrcs_.end()) {
958 // Not to us.
959 return;
960 }
961
962 rtcpPacketInformation.xr_dlrr_item = true;
963
964 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
965 // _criticalSectionRTCPReceiver.
966 _criticalSectionRTCPReceiver->Leave();
967
968 int64_t send_time_ms;
969 bool found = _rtpRtcp.SendTimeOfXrRrReport(
970 packet.XRDLRRReportBlockItem.LastRR, &send_time_ms);
971
972 _criticalSectionRTCPReceiver->Enter();
973
974 if (!found) {
975 return;
976 }
977
978 // The DelayLastRR field is in units of 1/65536 sec.
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000979 uint32_t delay_rr_ms =
980 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0x0000ffff) * 1000) >> 16) +
981 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0xffff0000) >> 16) * 1000);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000982
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000983 int32_t rtt = _clock->CurrentNtpInMilliseconds() - delay_rr_ms - send_time_ms;
984
985 xr_rr_rtt_ms_ = static_cast<uint16_t>(std::max(rtt, 1));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000986
987 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
988}
989
niklase@google.com470e71d2011-07-07 08:21:25 +0000990// no need for critsect we have _criticalSectionRTCPReceiver
991void
992RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
993 RTCPPacketInformation& rtcpPacketInformation)
994{
995 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
996
997 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
998
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000999 if(rtcpPacket.XRVOIPMetricItem.SSRC == main_ssrc_)
niklase@google.com470e71d2011-07-07 08:21:25 +00001000 {
1001 // Store VoIP metrics block if it's about me
1002 // from OriginatorSSRC do we filter it?
1003 // rtcpPacket.XR.OriginatorSSRC;
1004
1005 RTCPVoIPMetric receivedVoIPMetrics;
1006 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
1007 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
1008 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
1009 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
1010 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
1011 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
1012 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
1013 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
1014 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
1015 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
1016 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
1017 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
1018 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
1019 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
1020 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
1021 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
1022 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
1023 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
1024 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
1025 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
1026
1027 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
1028
1029 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
1030 }
1031 rtcpParser.Iterate();
1032}
1033
1034// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001035void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
1036 RTCPPacketInformation& rtcpPacketInformation) {
1037 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001038 if (main_ssrc_ == rtcpPacket.PLI.MediaSSRC) {
justinlin@chromium.org7bfb3a32013-05-13 22:59:00 +00001039 TRACE_EVENT_INSTANT0("webrtc_rtp", "PLI");
1040
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001041 ++packet_type_counter_.pli_packets;
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001042 // Received a signal that we need to send a new key frame.
1043 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
1044 }
1045 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001046}
1047
1048// no need for critsect we have _criticalSectionRTCPReceiver
1049void
1050RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
1051 RTCPPacketInformation& rtcpPacketInformation)
1052{
1053 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1054
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001055 uint32_t senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001056 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
1057 if (ptrReceiveInfo == NULL)
1058 {
1059 // This remote SSRC must be saved before.
1060 rtcpParser.Iterate();
1061 return;
1062 }
1063 if(rtcpPacket.TMMBR.MediaSSRC)
1064 {
1065 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
1066 // in relay mode this is a valid number
1067 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
1068 }
1069
1070 // Use packet length to calc max number of TMMBR blocks
1071 // each TMMBR block is 8 bytes
1072 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
1073
1074 // sanity
1075 if(maxNumOfTMMBRBlocks > 200) // we can't have more than what's in one packet
1076 {
1077 assert(false);
1078 rtcpParser.Iterate();
1079 return;
1080 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001081 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((uint32_t)maxNumOfTMMBRBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001082
1083 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1084 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode)
1085 {
1086 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
1087 pktType = rtcpParser.Iterate();
1088 }
1089}
1090
1091// no need for critsect we have _criticalSectionRTCPReceiver
1092void
1093RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
1094 const RTCPUtility::RTCPPacket& rtcpPacket,
1095 RTCPPacketInformation& rtcpPacketInformation,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001096 const uint32_t senderSSRC)
niklase@google.com470e71d2011-07-07 08:21:25 +00001097{
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001098 if (main_ssrc_ == rtcpPacket.TMMBRItem.SSRC &&
niklase@google.com470e71d2011-07-07 08:21:25 +00001099 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
1100 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001101 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001102 _clock->TimeInMilliseconds());
niklase@google.com470e71d2011-07-07 08:21:25 +00001103 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
1104 }
1105}
1106
1107// no need for critsect we have _criticalSectionRTCPReceiver
1108void
hta@webrtc.org9d54cd12012-04-30 08:24:55 +00001109RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
1110 RTCPPacketInformation& rtcpPacketInformation)
niklase@google.com470e71d2011-07-07 08:21:25 +00001111{
1112 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1113 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.TMMBN.SenderSSRC);
1114 if (ptrReceiveInfo == NULL)
1115 {
1116 // This remote SSRC must be saved before.
1117 rtcpParser.Iterate();
1118 return;
1119 }
hta@webrtc.org9d54cd12012-04-30 08:24:55 +00001120 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +00001121 // Use packet length to calc max number of TMMBN blocks
1122 // each TMMBN block is 8 bytes
1123 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
1124
1125 // sanity
1126 if(maxNumOfTMMBNBlocks > 200) // we cant have more than what's in one packet
1127 {
1128 assert(false);
1129 rtcpParser.Iterate();
1130 return;
1131 }
1132
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001133 ptrReceiveInfo->VerifyAndAllocateBoundingSet((uint32_t)maxNumOfTMMBNBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001134
1135 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1136 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode)
1137 {
1138 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
1139 pktType = rtcpParser.Iterate();
1140 }
1141}
1142
1143// no need for critsect we have _criticalSectionRTCPReceiver
1144void
1145RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
1146 RTCPPacketInformation& rtcpPacketInformation)
1147{
1148 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
1149 rtcpParser.Iterate();
1150}
1151
1152// no need for critsect we have _criticalSectionRTCPReceiver
1153void
1154RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
1155 const RTCPUtility::RTCPPacket& rtcpPacket)
1156{
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001157 receiveInfo.TmmbnBoundingSet.AddEntry(
1158 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
1159 rtcpPacket.TMMBNItem.MeasuredOverhead,
1160 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001161}
1162
1163// no need for critsect we have _criticalSectionRTCPReceiver
1164void
1165RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
1166 RTCPPacketInformation& rtcpPacketInformation)
1167{
1168 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001169 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1170 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode)
1171 {
1172 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1173 pktType = rtcpParser.Iterate();
1174 }
1175}
1176
1177// no need for critsect we have _criticalSectionRTCPReceiver
1178void
1179RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1180 RTCPPacketInformation& rtcpPacketInformation)
1181{
1182 // in theory there could be multiple slices lost
1183 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1184 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
1185}
1186
1187void
1188RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1189 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1190{
1191 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001192 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1193 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1194 {
1195 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1196 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1197 {
1198 // to us unknown
1199 // continue
1200 rtcpParser.Iterate();
1201 return;
1202 }
1203 rtcpPacketInformation.rpsiPictureId = 0;
1204
1205 // convert NativeBitString to rpsiPictureId
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001206 uint8_t numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1207 for(uint8_t n = 0; n < (numberOfBytes-1); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001208 {
1209 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1210 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1211 }
1212 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1213 }
1214}
1215
1216// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001217void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1218 RTCPPacketInformation& rtcpPacketInformation) {
1219 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1220 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1221 pktType = rtcpParser.Iterate();
1222 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1223 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1224 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001225 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001226 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001227}
1228
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001229// no need for critsect we have _criticalSectionRTCPReceiver
1230void
1231RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1232 RTCPPacketInformation& rtcpPacketInformation)
1233{
1234 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1235
1236 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1237 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode)
1238 {
1239 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1240 pktType = rtcpParser.Iterate();
1241 }
1242}
1243
1244void
1245RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1246 RTCPPacketInformation& rtcpPacketInformation)
1247{
1248 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1249 rtcpPacketInformation.interArrivalJitter =
1250 rtcpPacket.ExtendedJitterReportItem.Jitter;
1251}
1252
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001253void RTCPReceiver::HandleREMBItem(
1254 RTCPUtility::RTCPParserV2& rtcpParser,
1255 RTCPPacketInformation& rtcpPacketInformation) {
1256 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1257 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1258 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1259 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001260}
1261
1262// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001263void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1264 RTCPPacketInformation& rtcpPacketInformation) {
1265 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1266 RTCPReceiveInformation* ptrReceiveInfo =
1267 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001268
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001269 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1270 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1271 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1272 pktType = rtcpParser.Iterate();
1273 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001274}
1275
1276// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001277void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1278 const RTCPUtility::RTCPPacket& rtcpPacket,
1279 RTCPPacketInformation& rtcpPacketInformation) {
1280 // Is it our sender that is requested to generate a new keyframe
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001281 if (main_ssrc_ != rtcpPacket.FIRItem.SSRC) {
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001282 return;
1283 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001284
1285 ++packet_type_counter_.fir_packets;
1286
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001287 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1288 // we don't know who this originate from
1289 if (receiveInfo) {
1290 // check if we have reported this FIRSequenceNumber before
1291 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1292 receiveInfo->lastFIRSequenceNumber) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001293 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001294 // sanity; don't go crazy with the callbacks
1295 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1296 receiveInfo->lastFIRRequest = now;
1297 receiveInfo->lastFIRSequenceNumber =
1298 rtcpPacket.FIRItem.CommandSequenceNumber;
1299 // received signal that we need to send a new key frame
1300 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1301 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001302 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001303 } else {
1304 // received signal that we need to send a new key frame
1305 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1306 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001307}
1308
1309void
1310RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1311 RTCPPacketInformation& rtcpPacketInformation)
1312{
1313 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1314
1315 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1316 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1317 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
1318
1319 rtcpParser.Iterate();
1320}
1321
1322void
1323RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1324 RTCPPacketInformation& rtcpPacketInformation)
1325{
1326 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1327
1328 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
1329
1330 rtcpParser.Iterate();
1331}
1332
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001333int32_t RTCPReceiver::UpdateTMMBR() {
1334 int32_t numBoundingSet = 0;
1335 uint32_t bitrate = 0;
1336 uint32_t accNumCandidates = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001337
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001338 int32_t size = TMMBRReceived(0, 0, NULL);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001339 if (size > 0) {
1340 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1341 // Get candidate set from receiver.
1342 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1343 } else {
1344 // Candidate set empty.
1345 VerifyAndAllocateCandidateSet(0); // resets candidate set
1346 }
1347 // Find bounding set
1348 TMMBRSet* boundingSet = NULL;
1349 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1350 if (numBoundingSet == -1) {
1351 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1352 "Failed to find TMMBR bounding set.");
1353 return -1;
1354 }
1355 // Set bounding set
1356 // Inform remote clients about the new bandwidth
1357 // inform the remote client
1358 _rtpRtcp.SetTMMBN(boundingSet);
1359
1360 // might trigger a TMMBN
1361 if (numBoundingSet == 0) {
1362 // owner of max bitrate request has timed out
1363 // empty bounding set has been sent
1364 return 0;
1365 }
1366 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001367 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001368 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001369 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1370 if (_cbRtcpBandwidthObserver) {
1371 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
1372 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id,
1373 "Set TMMBR request:%d kbps", bitrate);
1374 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001375 }
1376 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001377}
1378
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001379void RTCPReceiver::RegisterRtcpStatisticsCallback(
1380 RtcpStatisticsCallback* callback) {
1381 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1382 if (callback != NULL)
1383 assert(stats_callback_ == NULL);
1384 stats_callback_ = callback;
1385}
1386
1387RtcpStatisticsCallback* RTCPReceiver::GetRtcpStatisticsCallback() {
1388 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1389 return stats_callback_;
1390}
1391
niklase@google.com470e71d2011-07-07 08:21:25 +00001392// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001393void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001394 RTCPPacketInformation& rtcpPacketInformation) {
1395 // Process TMMBR and REMB first to avoid multiple callbacks
1396 // to OnNetworkChanged.
1397 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
1398 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1399 "SIG [RTCP] Incoming TMMBR to id:%d", _id);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001400
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001401 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1402 UpdateTMMBR();
1403 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001404 unsigned int local_ssrc = 0;
1405 {
1406 // We don't want to hold this critsect when triggering the callbacks below.
1407 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001408 local_ssrc = main_ssrc_;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001409 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001410 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1411 _rtpRtcp.OnRequestSendReport();
1412 }
1413 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001414 if (rtcpPacketInformation.nackSequenceNumbers.size() > 0) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001415 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1416 "SIG [RTCP] Incoming NACK length:%d",
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001417 rtcpPacketInformation.nackSequenceNumbers.size());
1418 _rtpRtcp.OnReceivedNACK(rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001419 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001420 }
1421 {
1422 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001423
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001424 // We need feedback that we have received a report block(s) so that we
1425 // can generate a new packet in a conference relay scenario, one received
1426 // report can generate several RTCP packets, based on number relayed/mixed
1427 // a send report block should go out to all receivers.
1428 if (_cbRtcpIntraFrameObserver) {
1429 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1430 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1431 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
1432 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1433 "SIG [RTCP] Incoming PLI from SSRC:0x%x",
1434 rtcpPacketInformation.remoteSSRC);
1435 } else {
1436 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1437 "SIG [RTCP] Incoming FIR from SSRC:0x%x",
1438 rtcpPacketInformation.remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001439 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001440 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001441 }
1442 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1443 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001444 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001445 }
1446 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1447 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001448 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001449 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001450 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001451 if (_cbRtcpBandwidthObserver) {
1452 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
1453 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1454 "SIG [RTCP] Incoming REMB:%d",
1455 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1456 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1457 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1458 }
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001459 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1460 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001461 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001462 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001463 rtcpPacketInformation.report_blocks,
1464 rtcpPacketInformation.rtt,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001465 now);
1466 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001467 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001468 if(_cbRtcpFeedback) {
solenberg@webrtc.org91811e22013-06-25 20:36:14 +00001469 if(!(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr)) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001470 _cbRtcpFeedback->OnReceiveReportReceived(_id,
1471 rtcpPacketInformation.remoteSSRC);
1472 }
1473 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpXrVoipMetric) {
1474 _cbRtcpFeedback->OnXRVoIPMetricReceived(_id,
1475 rtcpPacketInformation.VoIPMetric);
1476 }
1477 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpApp) {
1478 _cbRtcpFeedback->OnApplicationDataReceived(_id,
1479 rtcpPacketInformation.applicationSubType,
1480 rtcpPacketInformation.applicationName,
1481 rtcpPacketInformation.applicationLength,
1482 rtcpPacketInformation.applicationData);
1483 }
1484 }
1485 }
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001486
1487 {
1488 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1489 if (stats_callback_) {
1490 for (ReportBlockList::const_iterator it =
1491 rtcpPacketInformation.report_blocks.begin();
1492 it != rtcpPacketInformation.report_blocks.end();
1493 ++it) {
1494 RtcpStatistics stats;
1495 stats.cumulative_lost = it->cumulativeLost;
1496 stats.extended_max_sequence_number = it->extendedHighSeqNum;
1497 stats.fraction_lost = it->fractionLost;
1498 stats.jitter = it->jitter;
1499
1500 stats_callback_->StatisticsUpdated(stats, local_ssrc);
1501 }
1502 }
1503 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001504}
1505
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001506int32_t RTCPReceiver::CNAME(const uint32_t remoteSSRC,
1507 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001508 assert(cName);
1509
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001510 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1511 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001512 if (cnameInfo == NULL) {
1513 return -1;
1514 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001515 cName[RTCP_CNAME_SIZE - 1] = 0;
1516 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1517 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001518}
1519
1520// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001521int32_t RTCPReceiver::TMMBRReceived(const uint32_t size,
1522 const uint32_t accNumCandidates,
1523 TMMBRSet* candidateSet) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001524 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001525
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001526 std::map<uint32_t, RTCPReceiveInformation*>::const_iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001527 receiveInfoIt = _receivedInfoMap.begin();
1528 if (receiveInfoIt == _receivedInfoMap.end()) {
1529 return -1;
1530 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001531 uint32_t num = accNumCandidates;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001532 if (candidateSet) {
1533 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1534 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1535 if (receiveInfo == NULL) {
1536 return 0;
1537 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001538 for (uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001539 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001540 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001541 _clock->TimeInMilliseconds()) == 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001542 num++;
1543 }
1544 }
1545 receiveInfoIt++;
1546 }
1547 } else {
1548 while (receiveInfoIt != _receivedInfoMap.end()) {
1549 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1550 if(receiveInfo == NULL) {
1551 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
1552 "%s failed to get RTCPReceiveInformation",
1553 __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +00001554 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001555 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001556 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001557 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001558 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001559 }
1560 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001561}
1562
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001563} // namespace webrtc