blob: 1d1e29167fe245ca92d942c4941dcbf58c21b14a [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.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));
niklase@google.com470e71d2011-07-07 08:21:25 +000060}
61
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000062RTCPReceiver::~RTCPReceiver() {
63 delete _criticalSectionRTCPReceiver;
64 delete _criticalSectionFeedbacks;
niklase@google.com470e71d2011-07-07 08:21:25 +000065
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000066 while (!_receivedReportBlockMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000067 std::map<uint32_t, RTCPReportBlockInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000068 _receivedReportBlockMap.begin();
69 delete first->second;
70 _receivedReportBlockMap.erase(first);
71 }
72 while (!_receivedInfoMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000073 std::map<uint32_t, RTCPReceiveInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000074 _receivedInfoMap.begin();
75 delete first->second;
76 _receivedInfoMap.erase(first);
77 }
78 while (!_receivedCnameMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000079 std::map<uint32_t, RTCPCnameInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000080 _receivedCnameMap.begin();
81 delete first->second;
82 _receivedCnameMap.erase(first);
83 }
niklase@google.com470e71d2011-07-07 08:21:25 +000084}
85
86void
pbos@webrtc.org2f446732013-04-08 11:08:41 +000087RTCPReceiver::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +000088{
89 _id = id;
90}
91
92RTCPMethod
93RTCPReceiver::Status() const
94{
95 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
96 return _method;
97}
98
pbos@webrtc.org2f446732013-04-08 11:08:41 +000099int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000100RTCPReceiver::SetRTCPStatus(const RTCPMethod method)
101{
102 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
103 _method = method;
104 return 0;
105}
106
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000107int64_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000108RTCPReceiver::LastReceived()
109{
110 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
111 return _lastReceived;
112}
113
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000114int64_t
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000115RTCPReceiver::LastReceivedReceiverReport() const {
116 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000117 int64_t last_received_rr = -1;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000118 for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin();
119 it != _receivedInfoMap.end(); ++it) {
120 if (it->second->lastTimeReceived > last_received_rr) {
121 last_received_rr = it->second->lastTimeReceived;
122 }
123 }
124 return last_received_rr;
125}
126
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000127int32_t
128RTCPReceiver::SetRemoteSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000129{
130 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
131
132 // new SSRC reset old reports
133 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
134 _lastReceivedSRNTPsecs = 0;
135 _lastReceivedSRNTPfrac = 0;
136
137 _remoteSSRC = ssrc;
138 return 0;
139}
140
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000141uint32_t RTCPReceiver::RemoteSSRC() const {
142 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
143 return _remoteSSRC;
144}
145
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000146void RTCPReceiver::RegisterRtcpObservers(
147 RtcpIntraFrameObserver* intra_frame_callback,
148 RtcpBandwidthObserver* bandwidth_callback,
149 RtcpFeedback* feedback_callback) {
150 CriticalSectionScoped lock(_criticalSectionFeedbacks);
151 _cbRtcpIntraFrameObserver = intra_frame_callback;
152 _cbRtcpBandwidthObserver = bandwidth_callback;
153 _cbRtcpFeedback = feedback_callback;
niklase@google.com470e71d2011-07-07 08:21:25 +0000154}
155
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000156void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
157 const std::set<uint32_t>& registered_ssrcs) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000158 uint32_t old_ssrc = 0;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000159 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000160 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000161 old_ssrc = main_ssrc_;
162 main_ssrc_ = main_ssrc;
163 registered_ssrcs_ = registered_ssrcs;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000164 }
165 {
166 CriticalSectionScoped lock(_criticalSectionFeedbacks);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000167 if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) {
168 _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc);
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000169 }
170 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000171}
172
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000173int32_t RTCPReceiver::ResetRTT(const uint32_t remoteSSRC) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000174 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
175 RTCPReportBlockInformation* reportBlock =
176 GetReportBlockInformation(remoteSSRC);
177 if (reportBlock == NULL) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000178 LOG(LS_WARNING) << "Failed to reset rtt for ssrc " << remoteSSRC;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000179 return -1;
180 }
181 reportBlock->RTT = 0;
182 reportBlock->avgRTT = 0;
183 reportBlock->minRTT = 0;
184 reportBlock->maxRTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000185 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000186}
187
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000188int32_t RTCPReceiver::RTT(uint32_t remoteSSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000189 uint16_t* RTT,
190 uint16_t* avgRTT,
191 uint16_t* minRTT,
192 uint16_t* maxRTT) const {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000193 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000194
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000195 RTCPReportBlockInformation* reportBlock =
196 GetReportBlockInformation(remoteSSRC);
197
198 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000199 return -1;
200 }
201 if (RTT) {
202 *RTT = reportBlock->RTT;
203 }
204 if (avgRTT) {
205 *avgRTT = reportBlock->avgRTT;
206 }
207 if (minRTT) {
208 *minRTT = reportBlock->minRTT;
209 }
210 if (maxRTT) {
211 *maxRTT = reportBlock->maxRTT;
212 }
213 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000214}
215
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000216bool RTCPReceiver::GetAndResetXrRrRtt(uint16_t* rtt_ms) {
217 assert(rtt_ms);
218 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
219 if (xr_rr_rtt_ms_ == 0) {
220 return false;
221 }
222 *rtt_ms = xr_rr_rtt_ms_;
223 xr_rr_rtt_ms_ = 0;
224 return true;
225}
226
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000227// TODO(pbos): Make this fail when we haven't received NTP.
228bool RTCPReceiver::NTP(uint32_t* ReceivedNTPsecs,
229 uint32_t* ReceivedNTPfrac,
230 uint32_t* RTCPArrivalTimeSecs,
231 uint32_t* RTCPArrivalTimeFrac,
232 uint32_t* rtcp_timestamp) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000233{
234 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
235 if(ReceivedNTPsecs)
236 {
237 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
238 }
239 if(ReceivedNTPfrac)
240 {
241 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
242 }
243 if(RTCPArrivalTimeFrac)
244 {
245 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
246 }
247 if(RTCPArrivalTimeSecs)
248 {
249 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
250 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000251 if (rtcp_timestamp) {
252 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
253 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000254 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000255}
256
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000257bool RTCPReceiver::LastReceivedXrReferenceTimeInfo(
258 RtcpReceiveTimeInfo* info) const {
259 assert(info);
260 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
261 if (_lastReceivedXRNTPsecs == 0 && _lastReceivedXRNTPfrac == 0) {
262 return false;
263 }
264
265 info->sourceSSRC = _remoteXRReceiveTimeInfo.sourceSSRC;
266 info->lastRR = _remoteXRReceiveTimeInfo.lastRR;
267
268 // Get the delay since last received report (RFC 3611).
269 uint32_t receive_time = RTCPUtility::MidNtp(_lastReceivedXRNTPsecs,
270 _lastReceivedXRNTPfrac);
271
272 uint32_t ntp_sec = 0;
273 uint32_t ntp_frac = 0;
274 _clock->CurrentNtp(ntp_sec, ntp_frac);
275 uint32_t now = RTCPUtility::MidNtp(ntp_sec, ntp_frac);
276
277 info->delaySinceLastRR = now - receive_time;
278 return true;
279}
280
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000281int32_t RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const {
282 assert(senderInfo);
283 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
284 if (_lastReceivedSRNTPsecs == 0) {
285 return -1;
286 }
287 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
288 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000289}
290
291// statistics
292// we can get multiple receive reports when we receive the report from a CE
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000293int32_t RTCPReceiver::StatisticsReceived(
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000294 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000295 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000296 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
297
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000298 std::map<uint32_t, RTCPReportBlockInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000299 _receivedReportBlockMap.begin();
300
301 while (it != _receivedReportBlockMap.end()) {
302 receiveBlocks->push_back(it->second->remoteReceiveBlock);
303 it++;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000304 }
305 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000306}
307
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000308void RTCPReceiver::GetPacketTypeCounter(
309 RtcpPacketTypeCounter* packet_counter) const {
310 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
311 *packet_counter = packet_type_counter_;
312}
313
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000314int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000315RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
316 RTCPUtility::RTCPParserV2* rtcpParser)
317{
318 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
319
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000320 _lastReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000321
322 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
323 while (pktType != RTCPUtility::kRtcpNotValidCode)
324 {
325 // Each "case" is responsible for iterate the parser to the
326 // next top level packet.
327 switch (pktType)
328 {
329 case RTCPUtility::kRtcpSrCode:
330 case RTCPUtility::kRtcpRrCode:
331 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
332 break;
333 case RTCPUtility::kRtcpSdesCode:
334 HandleSDES(*rtcpParser);
335 break;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000336 case RTCPUtility::kRtcpXrHeaderCode:
337 HandleXrHeader(*rtcpParser, rtcpPacketInformation);
338 break;
339 case RTCPUtility::kRtcpXrReceiverReferenceTimeCode:
340 HandleXrReceiveReferenceTime(*rtcpParser, rtcpPacketInformation);
341 break;
342 case RTCPUtility::kRtcpXrDlrrReportBlockCode:
343 HandleXrDlrrReportBlock(*rtcpParser, rtcpPacketInformation);
344 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000345 case RTCPUtility::kRtcpXrVoipMetricCode:
346 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
347 break;
348 case RTCPUtility::kRtcpByeCode:
349 HandleBYE(*rtcpParser);
350 break;
351 case RTCPUtility::kRtcpRtpfbNackCode:
352 HandleNACK(*rtcpParser, rtcpPacketInformation);
353 break;
354 case RTCPUtility::kRtcpRtpfbTmmbrCode:
355 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
356 break;
357 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000358 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000359 break;
360 case RTCPUtility::kRtcpRtpfbSrReqCode:
361 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
362 break;
363 case RTCPUtility::kRtcpPsfbPliCode:
364 HandlePLI(*rtcpParser, rtcpPacketInformation);
365 break;
366 case RTCPUtility::kRtcpPsfbSliCode:
367 HandleSLI(*rtcpParser, rtcpPacketInformation);
368 break;
369 case RTCPUtility::kRtcpPsfbRpsiCode:
370 HandleRPSI(*rtcpParser, rtcpPacketInformation);
371 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000372 case RTCPUtility::kRtcpExtendedIjCode:
373 HandleIJ(*rtcpParser, rtcpPacketInformation);
374 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000375 case RTCPUtility::kRtcpPsfbFirCode:
376 HandleFIR(*rtcpParser, rtcpPacketInformation);
377 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000378 case RTCPUtility::kRtcpPsfbAppCode:
379 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
380 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000381 case RTCPUtility::kRtcpAppCode:
382 // generic application messages
383 HandleAPP(*rtcpParser, rtcpPacketInformation);
384 break;
385 case RTCPUtility::kRtcpAppItemCode:
386 // generic application messages
387 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
388 break;
389 default:
390 rtcpParser->Iterate();
391 break;
392 }
393 pktType = rtcpParser->PacketType();
394 }
395 return 0;
396}
397
398// no need for critsect we have _criticalSectionRTCPReceiver
399void
400RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
401 RTCPPacketInformation& rtcpPacketInformation)
402{
403 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
404 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
405
406 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
407
408 // SR.SenderSSRC
409 // The synchronization source identifier for the originator of this SR packet
410
411 // rtcpPacket.RR.SenderSSRC
412 // The source of the packet sender, same as of SR? or is this a CE?
413
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000414 const uint32_t remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
415 const uint8_t numberOfReportBlocks = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.NumberOfReportBlocks:rtcpPacket.SR.NumberOfReportBlocks;
niklase@google.com470e71d2011-07-07 08:21:25 +0000416
417 rtcpPacketInformation.remoteSSRC = remoteSSRC;
418
419 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
420 if (!ptrReceiveInfo)
421 {
422 rtcpParser.Iterate();
423 return;
424 }
425
426 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
427 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000428 TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
429 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000430 "ssrc", main_ssrc_);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000431
niklase@google.com470e71d2011-07-07 08:21:25 +0000432 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
433 {
434 // only signal that we have received a SR when we accept one
435 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
436
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000437 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
438 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
439 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
440
niklase@google.com470e71d2011-07-07 08:21:25 +0000441 // We will only store the send report from one source, but
442 // we will store all the receive block
443
444 // Save the NTP time of this report
445 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
446 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
447 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
448 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
449 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
450
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000451 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000452 }
453 else
454 {
455 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
456 }
457 } else
458 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000459 TRACE_EVENT_INSTANT2("webrtc_rtp", "RR",
460 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000461 "ssrc", main_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000462
463 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
464 }
465 UpdateReceiveInformation(*ptrReceiveInfo);
466
467 rtcpPacketType = rtcpParser.Iterate();
468
469 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
470 {
471 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC, numberOfReportBlocks);
472 rtcpPacketType = rtcpParser.Iterate();
473 }
474}
475
476// no need for critsect we have _criticalSectionRTCPReceiver
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000477void RTCPReceiver::HandleReportBlock(
478 const RTCPUtility::RTCPPacket& rtcpPacket,
479 RTCPPacketInformation& rtcpPacketInformation,
480 const uint32_t remoteSSRC,
481 const uint8_t numberOfReportBlocks)
482 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000483 // This will be called once per report block in the RTCP packet.
484 // We filter out all report blocks that are not for us.
485 // Each packet has max 31 RR blocks.
486 //
487 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000488
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000489 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
490 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000491
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000492 // Filter out all report blocks that are not for us.
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000493 if (registered_ssrcs_.find(rtcpPacket.ReportBlockItem.SSRC) ==
494 registered_ssrcs_.end()) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000495 // This block is not for us ignore it.
496 return;
497 }
498
499 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
500 // _criticalSectionRTCPReceiver.
501 _criticalSectionRTCPReceiver->Leave();
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000502 uint32_t sendTimeMS =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000503 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
504 _criticalSectionRTCPReceiver->Enter();
505
506 RTCPReportBlockInformation* reportBlock =
507 CreateReportBlockInformation(remoteSSRC);
508 if (reportBlock == NULL) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000509 LOG(LS_WARNING) << "Failed to CreateReportBlockInformation("
510 << remoteSSRC << ")";
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000511 return;
512 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000513
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000514 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000515 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
516 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
517 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
518 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
519 reportBlock->remoteReceiveBlock.cumulativeLost =
520 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000521 if (rb.ExtendedHighestSequenceNumber >
522 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
523 // We have successfully delivered new RTP packets to the remote side after
524 // the last RR was sent from the remote side.
525 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000526 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000527 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
528 rb.ExtendedHighestSequenceNumber;
529 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
530 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
531 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
532
533 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
534 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
535 }
536
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000537 uint32_t delaySinceLastSendReport =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000538 rtcpPacket.ReportBlockItem.DelayLastSR;
539
540 // local NTP time when we received this
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000541 uint32_t lastReceivedRRNTPsecs = 0;
542 uint32_t lastReceivedRRNTPfrac = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000543
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000544 _clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000545
546 // time when we received this in MS
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000547 uint32_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
548 lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000549
550 // Estimate RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000551 uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000552 d /= 65536;
553 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
554
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000555 int32_t RTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000556
557 if (sendTimeMS > 0) {
558 RTT = receiveTimeMS - d - sendTimeMS;
559 if (RTT <= 0) {
560 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000561 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000562 if (RTT > reportBlock->maxRTT) {
563 // store max RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000564 reportBlock->maxRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000565 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000566 if (reportBlock->minRTT == 0) {
567 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000568 reportBlock->minRTT = (uint16_t) RTT;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000569 } else if (RTT < reportBlock->minRTT) {
570 // Store min RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000571 reportBlock->minRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000572 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000573 // store last RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000574 reportBlock->RTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000575
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000576 // store average RTT
577 if (reportBlock->numAverageCalcs != 0) {
578 float ac = static_cast<float> (reportBlock->numAverageCalcs);
579 float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT)
580 + ((1 / (ac + 1)) * RTT);
581 reportBlock->avgRTT = static_cast<int> (newAverage + 0.5f);
582 } else {
583 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000584 reportBlock->avgRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000585 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000586 reportBlock->numAverageCalcs++;
587 }
588
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000589 TRACE_COUNTER_ID1("webrtc_rtp", "RR_RTT", rb.SSRC, RTT);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000590
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000591 rtcpPacketInformation.AddReportInfo(*reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000592}
593
594RTCPReportBlockInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000595RTCPReceiver::CreateReportBlockInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000596 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000597
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000598 std::map<uint32_t, RTCPReportBlockInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000599 _receivedReportBlockMap.find(remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000600
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000601 RTCPReportBlockInformation* ptrReportBlockInfo = NULL;
602 if (it != _receivedReportBlockMap.end()) {
603 ptrReportBlockInfo = it->second;
604 } else {
605 ptrReportBlockInfo = new RTCPReportBlockInformation;
606 _receivedReportBlockMap[remoteSSRC] = ptrReportBlockInfo;
607 }
608 return ptrReportBlockInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000609}
610
611RTCPReportBlockInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000612RTCPReceiver::GetReportBlockInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000613 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000614
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000615 std::map<uint32_t, RTCPReportBlockInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000616 _receivedReportBlockMap.find(remoteSSRC);
617
618 if (it == _receivedReportBlockMap.end()) {
619 return NULL;
620 }
621 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000622}
623
624RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000625RTCPReceiver::CreateCnameInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000626 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000627
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000628 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000629 _receivedCnameMap.find(remoteSSRC);
630
631 if (it != _receivedCnameMap.end()) {
632 return it->second;
633 }
634 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000635 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000636 _receivedCnameMap[remoteSSRC] = cnameInfo;
637 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000638}
639
640RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000641RTCPReceiver::GetCnameInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000642 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000643
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000644 std::map<uint32_t, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000645 _receivedCnameMap.find(remoteSSRC);
646
647 if (it == _receivedCnameMap.end()) {
648 return NULL;
649 }
650 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000651}
652
653RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000654RTCPReceiver::CreateReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000655 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000656
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000657 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000658 _receivedInfoMap.find(remoteSSRC);
659
660 if (it != _receivedInfoMap.end()) {
661 return it->second;
662 }
663 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
664 _receivedInfoMap[remoteSSRC] = receiveInfo;
665 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000666}
667
668RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000669RTCPReceiver::GetReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000670 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000671
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000672 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000673 _receivedInfoMap.find(remoteSSRC);
674 if (it == _receivedInfoMap.end()) {
675 return NULL;
676 }
677 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000678}
679
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000680void RTCPReceiver::UpdateReceiveInformation(
681 RTCPReceiveInformation& receiveInformation) {
682 // Update that this remote is alive
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000683 receiveInformation.lastTimeReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000684}
685
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000686bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
687 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
688 if (_lastReceivedRrMs == 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() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000693 // Reset the timer to only trigger one log.
694 _lastReceivedRrMs = 0;
695 return true;
696 }
697 return false;
698}
699
700bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
701 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
702 if (_lastIncreasedSequenceNumberMs == 0)
703 return false;
704
705 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000706 if (_clock->TimeInMilliseconds() > _lastIncreasedSequenceNumberMs +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000707 time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000708 // Reset the timer to only trigger one log.
709 _lastIncreasedSequenceNumberMs = 0;
710 return true;
711 }
712 return false;
713}
714
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000715bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
716 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000717
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000718 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000719 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000720
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000721 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000722 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000723
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000724 while (receiveInfoIt != _receivedInfoMap.end()) {
725 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
726 if (receiveInfo == NULL) {
727 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000728 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000729 // time since last received rtcp packet
730 // when we dont have a lastTimeReceived and the object is marked
731 // readyForDelete it's removed from the map
732 if (receiveInfo->lastTimeReceived) {
733 /// use audio define since we don't know what interval the remote peer is
734 // using
735 if ((timeNow - receiveInfo->lastTimeReceived) >
736 5 * RTCP_INTERVAL_AUDIO_MS) {
737 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000738 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000739 // prevent that we call this over and over again
740 receiveInfo->lastTimeReceived = 0;
741 // send new TMMBN to all channels using the default codec
742 updateBoundingSet = true;
743 }
744 receiveInfoIt++;
745 } else if (receiveInfo->readyForDelete) {
746 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000747 std::map<uint32_t, RTCPReceiveInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000748 receiveInfoItemToBeErased = receiveInfoIt;
749 receiveInfoIt++;
750 delete receiveInfoItemToBeErased->second;
751 _receivedInfoMap.erase(receiveInfoItemToBeErased);
752 } else {
753 receiveInfoIt++;
754 }
755 }
756 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000757}
758
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000759int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000760 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000761
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000762 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000763 _receivedInfoMap.find(_remoteSSRC);
764
765 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000766 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000767 }
768 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
769 if (receiveInfo == NULL) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000770 return -1;
771 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000772 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000773 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000774 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000775 for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000776 i++) {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000777 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000778 // owner of bounding set
779 tmmbrOwner = true;
780 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000781 boundingSetRec->SetEntry(i,
782 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
783 receiveInfo->TmmbnBoundingSet.PacketOH(i),
784 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000785 }
786 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000787 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000788}
789
790// no need for critsect we have _criticalSectionRTCPReceiver
791void
792RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser)
793{
794 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
795 while (pktType == RTCPUtility::kRtcpSdesChunkCode)
796 {
797 HandleSDESChunk(rtcpParser);
798 pktType = rtcpParser.Iterate();
799 }
800}
801
802// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000803void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
804 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
805 RTCPCnameInformation* cnameInfo =
806 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
807 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000808
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000809 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
810 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000811}
812
813// no need for critsect we have _criticalSectionRTCPReceiver
814void
815RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
816 RTCPPacketInformation& rtcpPacketInformation)
817{
818 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000819 if (main_ssrc_ != rtcpPacket.NACK.MediaSSRC)
niklase@google.com470e71d2011-07-07 08:21:25 +0000820 {
821 // Not to us.
822 rtcpParser.Iterate();
823 return;
824 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000825 rtcpPacketInformation.ResetNACKPacketIdArray();
826
827 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
828 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode)
829 {
830 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
831 pktType = rtcpParser.Iterate();
832 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000833
834 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
835 ++packet_type_counter_.nack_packets;
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000836 packet_type_counter_.nack_requests = nack_stats_.requests();
837 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000838 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000839}
840
841// no need for critsect we have _criticalSectionRTCPReceiver
842void
843RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
844 RTCPPacketInformation& rtcpPacketInformation)
845{
846 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000847 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000848
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000849 uint16_t bitMask = rtcpPacket.NACKItem.BitMask;
niklase@google.com470e71d2011-07-07 08:21:25 +0000850 if(bitMask)
851 {
852 for(int i=1; i <= 16; ++i)
853 {
854 if(bitMask & 0x01)
855 {
856 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000857 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID + i);
niklase@google.com470e71d2011-07-07 08:21:25 +0000858 }
859 bitMask = bitMask >>1;
860 }
861 }
862
863 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
864}
865
866// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000867void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
868 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000869
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000870 // clear our lists
871 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000872 std::map<uint32_t, RTCPReportBlockInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000873 reportBlockInfoIt = _receivedReportBlockMap.find(
874 rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000875
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000876 if (reportBlockInfoIt != _receivedReportBlockMap.end()) {
877 delete reportBlockInfoIt->second;
878 _receivedReportBlockMap.erase(reportBlockInfoIt);
879 }
880 // we can't delete it due to TMMBR
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000881 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000882 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000883
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000884 if (receiveInfoIt != _receivedInfoMap.end()) {
885 receiveInfoIt->second->readyForDelete = true;
886 }
887
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000888 std::map<uint32_t, RTCPCnameInformation*>::iterator cnameInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000889 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
890
891 if (cnameInfoIt != _receivedCnameMap.end()) {
892 delete cnameInfoIt->second;
893 _receivedCnameMap.erase(cnameInfoIt);
894 }
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000895 xr_rr_rtt_ms_ = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000896 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000897}
898
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000899void RTCPReceiver::HandleXrHeader(
900 RTCPUtility::RTCPParserV2& parser,
901 RTCPPacketInformation& rtcpPacketInformation) {
902 const RTCPUtility::RTCPPacket& packet = parser.Packet();
903
904 rtcpPacketInformation.xr_originator_ssrc = packet.XR.OriginatorSSRC;
905
906 parser.Iterate();
907}
908
909void RTCPReceiver::HandleXrReceiveReferenceTime(
910 RTCPUtility::RTCPParserV2& parser,
911 RTCPPacketInformation& rtcpPacketInformation) {
912 const RTCPUtility::RTCPPacket& packet = parser.Packet();
913
914 _remoteXRReceiveTimeInfo.sourceSSRC =
915 rtcpPacketInformation.xr_originator_ssrc;
916
917 _remoteXRReceiveTimeInfo.lastRR = RTCPUtility::MidNtp(
918 packet.XRReceiverReferenceTimeItem.NTPMostSignificant,
919 packet.XRReceiverReferenceTimeItem.NTPLeastSignificant);
920
921 _clock->CurrentNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);
922
923 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
924
925 parser.Iterate();
926}
927
928void RTCPReceiver::HandleXrDlrrReportBlock(
929 RTCPUtility::RTCPParserV2& parser,
930 RTCPPacketInformation& rtcpPacketInformation) {
931 const RTCPUtility::RTCPPacket& packet = parser.Packet();
932 // Iterate through sub-block(s), if any.
933 RTCPUtility::RTCPPacketTypes packet_type = parser.Iterate();
934
935 while (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
936 HandleXrDlrrReportBlockItem(packet, rtcpPacketInformation);
937 packet_type = parser.Iterate();
938 }
939}
940
941void RTCPReceiver::HandleXrDlrrReportBlockItem(
942 const RTCPUtility::RTCPPacket& packet,
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000943 RTCPPacketInformation& rtcpPacketInformation)
944 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000945 if (registered_ssrcs_.find(packet.XRDLRRReportBlockItem.SSRC) ==
946 registered_ssrcs_.end()) {
947 // Not to us.
948 return;
949 }
950
951 rtcpPacketInformation.xr_dlrr_item = true;
952
953 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
954 // _criticalSectionRTCPReceiver.
955 _criticalSectionRTCPReceiver->Leave();
956
957 int64_t send_time_ms;
958 bool found = _rtpRtcp.SendTimeOfXrRrReport(
959 packet.XRDLRRReportBlockItem.LastRR, &send_time_ms);
960
961 _criticalSectionRTCPReceiver->Enter();
962
963 if (!found) {
964 return;
965 }
966
967 // The DelayLastRR field is in units of 1/65536 sec.
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000968 uint32_t delay_rr_ms =
969 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0x0000ffff) * 1000) >> 16) +
970 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0xffff0000) >> 16) * 1000);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000971
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000972 int32_t rtt = _clock->CurrentNtpInMilliseconds() - delay_rr_ms - send_time_ms;
973
974 xr_rr_rtt_ms_ = static_cast<uint16_t>(std::max(rtt, 1));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000975
976 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
977}
978
niklase@google.com470e71d2011-07-07 08:21:25 +0000979// no need for critsect we have _criticalSectionRTCPReceiver
980void
981RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
982 RTCPPacketInformation& rtcpPacketInformation)
983{
984 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
985
986 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
987
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000988 if(rtcpPacket.XRVOIPMetricItem.SSRC == main_ssrc_)
niklase@google.com470e71d2011-07-07 08:21:25 +0000989 {
990 // Store VoIP metrics block if it's about me
991 // from OriginatorSSRC do we filter it?
992 // rtcpPacket.XR.OriginatorSSRC;
993
994 RTCPVoIPMetric receivedVoIPMetrics;
995 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
996 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
997 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
998 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
999 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
1000 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
1001 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
1002 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
1003 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
1004 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
1005 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
1006 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
1007 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
1008 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
1009 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
1010 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
1011 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
1012 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
1013 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
1014 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
1015
1016 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
1017
1018 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
1019 }
1020 rtcpParser.Iterate();
1021}
1022
1023// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001024void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
1025 RTCPPacketInformation& rtcpPacketInformation) {
1026 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001027 if (main_ssrc_ == rtcpPacket.PLI.MediaSSRC) {
justinlin@chromium.org7bfb3a32013-05-13 22:59:00 +00001028 TRACE_EVENT_INSTANT0("webrtc_rtp", "PLI");
1029
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001030 ++packet_type_counter_.pli_packets;
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001031 // Received a signal that we need to send a new key frame.
1032 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
1033 }
1034 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001035}
1036
1037// no need for critsect we have _criticalSectionRTCPReceiver
1038void
1039RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
1040 RTCPPacketInformation& rtcpPacketInformation)
1041{
1042 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1043
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001044 uint32_t senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001045 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
1046 if (ptrReceiveInfo == NULL)
1047 {
1048 // This remote SSRC must be saved before.
1049 rtcpParser.Iterate();
1050 return;
1051 }
1052 if(rtcpPacket.TMMBR.MediaSSRC)
1053 {
1054 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
1055 // in relay mode this is a valid number
1056 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
1057 }
1058
1059 // Use packet length to calc max number of TMMBR blocks
1060 // each TMMBR block is 8 bytes
1061 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
1062
1063 // sanity
1064 if(maxNumOfTMMBRBlocks > 200) // we can't have more than what's in one packet
1065 {
1066 assert(false);
1067 rtcpParser.Iterate();
1068 return;
1069 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001070 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((uint32_t)maxNumOfTMMBRBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001071
1072 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1073 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode)
1074 {
1075 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
1076 pktType = rtcpParser.Iterate();
1077 }
1078}
1079
1080// no need for critsect we have _criticalSectionRTCPReceiver
1081void
1082RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
1083 const RTCPUtility::RTCPPacket& rtcpPacket,
1084 RTCPPacketInformation& rtcpPacketInformation,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001085 const uint32_t senderSSRC)
niklase@google.com470e71d2011-07-07 08:21:25 +00001086{
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001087 if (main_ssrc_ == rtcpPacket.TMMBRItem.SSRC &&
niklase@google.com470e71d2011-07-07 08:21:25 +00001088 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
1089 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001090 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001091 _clock->TimeInMilliseconds());
niklase@google.com470e71d2011-07-07 08:21:25 +00001092 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
1093 }
1094}
1095
1096// no need for critsect we have _criticalSectionRTCPReceiver
1097void
hta@webrtc.org9d54cd12012-04-30 08:24:55 +00001098RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
1099 RTCPPacketInformation& rtcpPacketInformation)
niklase@google.com470e71d2011-07-07 08:21:25 +00001100{
1101 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1102 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.TMMBN.SenderSSRC);
1103 if (ptrReceiveInfo == NULL)
1104 {
1105 // This remote SSRC must be saved before.
1106 rtcpParser.Iterate();
1107 return;
1108 }
hta@webrtc.org9d54cd12012-04-30 08:24:55 +00001109 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +00001110 // Use packet length to calc max number of TMMBN blocks
1111 // each TMMBN block is 8 bytes
1112 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
1113
1114 // sanity
1115 if(maxNumOfTMMBNBlocks > 200) // we cant have more than what's in one packet
1116 {
1117 assert(false);
1118 rtcpParser.Iterate();
1119 return;
1120 }
1121
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001122 ptrReceiveInfo->VerifyAndAllocateBoundingSet((uint32_t)maxNumOfTMMBNBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001123
1124 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1125 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode)
1126 {
1127 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
1128 pktType = rtcpParser.Iterate();
1129 }
1130}
1131
1132// no need for critsect we have _criticalSectionRTCPReceiver
1133void
1134RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
1135 RTCPPacketInformation& rtcpPacketInformation)
1136{
1137 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
1138 rtcpParser.Iterate();
1139}
1140
1141// no need for critsect we have _criticalSectionRTCPReceiver
1142void
1143RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
1144 const RTCPUtility::RTCPPacket& rtcpPacket)
1145{
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001146 receiveInfo.TmmbnBoundingSet.AddEntry(
1147 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
1148 rtcpPacket.TMMBNItem.MeasuredOverhead,
1149 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001150}
1151
1152// no need for critsect we have _criticalSectionRTCPReceiver
1153void
1154RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
1155 RTCPPacketInformation& rtcpPacketInformation)
1156{
1157 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001158 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1159 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode)
1160 {
1161 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1162 pktType = rtcpParser.Iterate();
1163 }
1164}
1165
1166// no need for critsect we have _criticalSectionRTCPReceiver
1167void
1168RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1169 RTCPPacketInformation& rtcpPacketInformation)
1170{
1171 // in theory there could be multiple slices lost
1172 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1173 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
1174}
1175
1176void
1177RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1178 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1179{
1180 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001181 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1182 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1183 {
1184 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1185 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1186 {
1187 // to us unknown
1188 // continue
1189 rtcpParser.Iterate();
1190 return;
1191 }
1192 rtcpPacketInformation.rpsiPictureId = 0;
1193
1194 // convert NativeBitString to rpsiPictureId
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001195 uint8_t numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1196 for(uint8_t n = 0; n < (numberOfBytes-1); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001197 {
1198 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1199 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1200 }
1201 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1202 }
1203}
1204
1205// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001206void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1207 RTCPPacketInformation& rtcpPacketInformation) {
1208 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1209 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1210 pktType = rtcpParser.Iterate();
1211 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1212 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1213 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001214 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001215 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001216}
1217
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001218// no need for critsect we have _criticalSectionRTCPReceiver
1219void
1220RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1221 RTCPPacketInformation& rtcpPacketInformation)
1222{
1223 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1224
1225 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1226 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode)
1227 {
1228 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1229 pktType = rtcpParser.Iterate();
1230 }
1231}
1232
1233void
1234RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1235 RTCPPacketInformation& rtcpPacketInformation)
1236{
1237 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1238 rtcpPacketInformation.interArrivalJitter =
1239 rtcpPacket.ExtendedJitterReportItem.Jitter;
1240}
1241
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001242void RTCPReceiver::HandleREMBItem(
1243 RTCPUtility::RTCPParserV2& rtcpParser,
1244 RTCPPacketInformation& rtcpPacketInformation) {
1245 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1246 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1247 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1248 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001249}
1250
1251// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001252void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1253 RTCPPacketInformation& rtcpPacketInformation) {
1254 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1255 RTCPReceiveInformation* ptrReceiveInfo =
1256 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001257
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001258 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1259 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1260 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1261 pktType = rtcpParser.Iterate();
1262 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001263}
1264
1265// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001266void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1267 const RTCPUtility::RTCPPacket& rtcpPacket,
1268 RTCPPacketInformation& rtcpPacketInformation) {
1269 // Is it our sender that is requested to generate a new keyframe
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001270 if (main_ssrc_ != rtcpPacket.FIRItem.SSRC) {
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001271 return;
1272 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001273
1274 ++packet_type_counter_.fir_packets;
1275
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001276 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1277 // we don't know who this originate from
1278 if (receiveInfo) {
1279 // check if we have reported this FIRSequenceNumber before
1280 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1281 receiveInfo->lastFIRSequenceNumber) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001282 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001283 // sanity; don't go crazy with the callbacks
1284 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1285 receiveInfo->lastFIRRequest = now;
1286 receiveInfo->lastFIRSequenceNumber =
1287 rtcpPacket.FIRItem.CommandSequenceNumber;
1288 // received signal that we need to send a new key frame
1289 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1290 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001291 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001292 } else {
1293 // received signal that we need to send a new key frame
1294 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1295 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001296}
1297
1298void
1299RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1300 RTCPPacketInformation& rtcpPacketInformation)
1301{
1302 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1303
1304 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1305 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1306 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
1307
1308 rtcpParser.Iterate();
1309}
1310
1311void
1312RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1313 RTCPPacketInformation& rtcpPacketInformation)
1314{
1315 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1316
1317 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
1318
1319 rtcpParser.Iterate();
1320}
1321
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001322int32_t RTCPReceiver::UpdateTMMBR() {
1323 int32_t numBoundingSet = 0;
1324 uint32_t bitrate = 0;
1325 uint32_t accNumCandidates = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001326
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001327 int32_t size = TMMBRReceived(0, 0, NULL);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001328 if (size > 0) {
1329 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1330 // Get candidate set from receiver.
1331 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1332 } else {
1333 // Candidate set empty.
1334 VerifyAndAllocateCandidateSet(0); // resets candidate set
1335 }
1336 // Find bounding set
1337 TMMBRSet* boundingSet = NULL;
1338 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1339 if (numBoundingSet == -1) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001340 LOG(LS_WARNING) << "Failed to find TMMBR bounding set.";
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001341 return -1;
1342 }
1343 // Set bounding set
1344 // Inform remote clients about the new bandwidth
1345 // inform the remote client
1346 _rtpRtcp.SetTMMBN(boundingSet);
1347
1348 // might trigger a TMMBN
1349 if (numBoundingSet == 0) {
1350 // owner of max bitrate request has timed out
1351 // empty bounding set has been sent
1352 return 0;
1353 }
1354 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001355 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001356 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001357 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1358 if (_cbRtcpBandwidthObserver) {
1359 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001360 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001361 }
1362 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001363}
1364
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001365void RTCPReceiver::RegisterRtcpStatisticsCallback(
1366 RtcpStatisticsCallback* callback) {
1367 CriticalSectionScoped cs(_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001368 stats_callback_ = callback;
1369}
1370
1371RtcpStatisticsCallback* RTCPReceiver::GetRtcpStatisticsCallback() {
1372 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1373 return stats_callback_;
1374}
1375
niklase@google.com470e71d2011-07-07 08:21:25 +00001376// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001377void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001378 RTCPPacketInformation& rtcpPacketInformation) {
1379 // Process TMMBR and REMB first to avoid multiple callbacks
1380 // to OnNetworkChanged.
1381 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001382 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1383 UpdateTMMBR();
1384 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001385 unsigned int local_ssrc = 0;
1386 {
1387 // We don't want to hold this critsect when triggering the callbacks below.
1388 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001389 local_ssrc = main_ssrc_;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001390 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001391 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1392 _rtpRtcp.OnRequestSendReport();
1393 }
1394 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001395 if (rtcpPacketInformation.nackSequenceNumbers.size() > 0) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001396 LOG(LS_VERBOSE) << "Incoming NACK length: "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001397 << rtcpPacketInformation.nackSequenceNumbers.size();
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001398 _rtpRtcp.OnReceivedNACK(rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001399 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001400 }
1401 {
1402 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001403
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001404 // We need feedback that we have received a report block(s) so that we
1405 // can generate a new packet in a conference relay scenario, one received
1406 // report can generate several RTCP packets, based on number relayed/mixed
1407 // a send report block should go out to all receivers.
1408 if (_cbRtcpIntraFrameObserver) {
1409 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1410 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1411 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001412 LOG(LS_VERBOSE) << "Incoming PLI from SSRC "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001413 << rtcpPacketInformation.remoteSSRC;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001414 } else {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001415 LOG(LS_VERBOSE) << "Incoming FIR from SSRC "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001416 << rtcpPacketInformation.remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001417 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001418 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001419 }
1420 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1421 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001422 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001423 }
1424 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1425 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001426 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001427 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001428 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001429 if (_cbRtcpBandwidthObserver) {
1430 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001431 LOG(LS_VERBOSE) << "Incoming REMB: "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001432 << rtcpPacketInformation.receiverEstimatedMaxBitrate;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001433 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1434 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1435 }
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001436 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1437 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001438 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001439 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001440 rtcpPacketInformation.report_blocks,
1441 rtcpPacketInformation.rtt,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001442 now);
1443 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001444 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001445 if(_cbRtcpFeedback) {
solenberg@webrtc.org91811e22013-06-25 20:36:14 +00001446 if(!(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr)) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001447 _cbRtcpFeedback->OnReceiveReportReceived(_id,
1448 rtcpPacketInformation.remoteSSRC);
1449 }
1450 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpXrVoipMetric) {
1451 _cbRtcpFeedback->OnXRVoIPMetricReceived(_id,
1452 rtcpPacketInformation.VoIPMetric);
1453 }
1454 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpApp) {
1455 _cbRtcpFeedback->OnApplicationDataReceived(_id,
1456 rtcpPacketInformation.applicationSubType,
1457 rtcpPacketInformation.applicationName,
1458 rtcpPacketInformation.applicationLength,
1459 rtcpPacketInformation.applicationData);
1460 }
1461 }
1462 }
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001463
1464 {
1465 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1466 if (stats_callback_) {
1467 for (ReportBlockList::const_iterator it =
1468 rtcpPacketInformation.report_blocks.begin();
1469 it != rtcpPacketInformation.report_blocks.end();
1470 ++it) {
1471 RtcpStatistics stats;
1472 stats.cumulative_lost = it->cumulativeLost;
1473 stats.extended_max_sequence_number = it->extendedHighSeqNum;
1474 stats.fraction_lost = it->fractionLost;
1475 stats.jitter = it->jitter;
1476
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001477 stats_callback_->StatisticsUpdated(stats, it->sourceSSRC);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001478 }
1479 }
1480 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001481}
1482
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001483int32_t RTCPReceiver::CNAME(const uint32_t remoteSSRC,
1484 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001485 assert(cName);
1486
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001487 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1488 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001489 if (cnameInfo == NULL) {
1490 return -1;
1491 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001492 cName[RTCP_CNAME_SIZE - 1] = 0;
1493 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1494 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001495}
1496
1497// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001498int32_t RTCPReceiver::TMMBRReceived(const uint32_t size,
1499 const uint32_t accNumCandidates,
1500 TMMBRSet* candidateSet) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001501 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001502
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001503 std::map<uint32_t, RTCPReceiveInformation*>::const_iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001504 receiveInfoIt = _receivedInfoMap.begin();
1505 if (receiveInfoIt == _receivedInfoMap.end()) {
1506 return -1;
1507 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001508 uint32_t num = accNumCandidates;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001509 if (candidateSet) {
1510 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1511 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1512 if (receiveInfo == NULL) {
1513 return 0;
1514 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001515 for (uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001516 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001517 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001518 _clock->TimeInMilliseconds()) == 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001519 num++;
1520 }
1521 }
1522 receiveInfoIt++;
1523 }
1524 } else {
1525 while (receiveInfoIt != _receivedInfoMap.end()) {
1526 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1527 if(receiveInfo == NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001528 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001529 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001530 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001531 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001532 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001533 }
1534 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001535}
1536
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001537} // namespace webrtc