blob: b03b68ffe66f87acbb3cd0bd2b1238b2309696d8 [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 _cbRtcpBandwidthObserver(NULL),
42 _cbRtcpIntraFrameObserver(NULL),
43 _criticalSectionRTCPReceiver(
44 CriticalSectionWrapper::CreateCriticalSection()),
stefan@webrtc.org28a331e2013-09-17 07:49:56 +000045 main_ssrc_(0),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000046 _remoteSSRC(0),
47 _remoteSenderInfo(),
48 _lastReceivedSRNTPsecs(0),
49 _lastReceivedSRNTPfrac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000050 _lastReceivedXRNTPsecs(0),
51 _lastReceivedXRNTPfrac(0),
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +000052 xr_rr_rtt_ms_(0),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000053 _receivedInfoMap(),
54 _packetTimeOutMS(0),
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000055 _lastReceivedRrMs(0),
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +000056 _lastIncreasedSequenceNumberMs(0),
57 stats_callback_(NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +000058 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
niklase@google.com470e71d2011-07-07 08:21:25 +000059}
60
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000061RTCPReceiver::~RTCPReceiver() {
62 delete _criticalSectionRTCPReceiver;
63 delete _criticalSectionFeedbacks;
niklase@google.com470e71d2011-07-07 08:21:25 +000064
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000065 while (!_receivedReportBlockMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000066 std::map<uint32_t, RTCPReportBlockInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000067 _receivedReportBlockMap.begin();
68 delete first->second;
69 _receivedReportBlockMap.erase(first);
70 }
71 while (!_receivedInfoMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000072 std::map<uint32_t, RTCPReceiveInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000073 _receivedInfoMap.begin();
74 delete first->second;
75 _receivedInfoMap.erase(first);
76 }
77 while (!_receivedCnameMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000078 std::map<uint32_t, RTCPCnameInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000079 _receivedCnameMap.begin();
80 delete first->second;
81 _receivedCnameMap.erase(first);
82 }
niklase@google.com470e71d2011-07-07 08:21:25 +000083}
84
85void
pbos@webrtc.org2f446732013-04-08 11:08:41 +000086RTCPReceiver::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +000087{
88 _id = id;
89}
90
91RTCPMethod
92RTCPReceiver::Status() const
93{
94 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
95 return _method;
96}
97
pbos@webrtc.org2f446732013-04-08 11:08:41 +000098int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +000099RTCPReceiver::SetRTCPStatus(const RTCPMethod method)
100{
101 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
102 _method = method;
103 return 0;
104}
105
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000106int64_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000107RTCPReceiver::LastReceived()
108{
109 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
110 return _lastReceived;
111}
112
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000113int64_t
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000114RTCPReceiver::LastReceivedReceiverReport() const {
115 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000116 int64_t last_received_rr = -1;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000117 for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin();
118 it != _receivedInfoMap.end(); ++it) {
119 if (it->second->lastTimeReceived > last_received_rr) {
120 last_received_rr = it->second->lastTimeReceived;
121 }
122 }
123 return last_received_rr;
124}
125
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000126int32_t
127RTCPReceiver::SetRemoteSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000128{
129 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
130
131 // new SSRC reset old reports
132 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
133 _lastReceivedSRNTPsecs = 0;
134 _lastReceivedSRNTPfrac = 0;
135
136 _remoteSSRC = ssrc;
137 return 0;
138}
139
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000140uint32_t RTCPReceiver::RemoteSSRC() const {
141 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
142 return _remoteSSRC;
143}
144
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000145void RTCPReceiver::RegisterRtcpObservers(
146 RtcpIntraFrameObserver* intra_frame_callback,
pbos@webrtc.orgece38902014-11-14 11:52:04 +0000147 RtcpBandwidthObserver* bandwidth_callback) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000148 CriticalSectionScoped lock(_criticalSectionFeedbacks);
149 _cbRtcpIntraFrameObserver = intra_frame_callback;
150 _cbRtcpBandwidthObserver = bandwidth_callback;
niklase@google.com470e71d2011-07-07 08:21:25 +0000151}
152
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000153void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
154 const std::set<uint32_t>& registered_ssrcs) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000155 uint32_t old_ssrc = 0;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000156 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000157 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000158 old_ssrc = main_ssrc_;
159 main_ssrc_ = main_ssrc;
160 registered_ssrcs_ = registered_ssrcs;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000161 }
162 {
163 CriticalSectionScoped lock(_criticalSectionFeedbacks);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000164 if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) {
165 _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc);
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000166 }
167 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000168}
169
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000170int32_t RTCPReceiver::ResetRTT(const uint32_t remoteSSRC) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000171 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
172 RTCPReportBlockInformation* reportBlock =
173 GetReportBlockInformation(remoteSSRC);
174 if (reportBlock == NULL) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000175 LOG(LS_WARNING) << "Failed to reset rtt for ssrc " << remoteSSRC;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000176 return -1;
177 }
178 reportBlock->RTT = 0;
179 reportBlock->avgRTT = 0;
180 reportBlock->minRTT = 0;
181 reportBlock->maxRTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000182 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000183}
184
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000185int32_t RTCPReceiver::RTT(uint32_t remoteSSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000186 uint16_t* RTT,
187 uint16_t* avgRTT,
188 uint16_t* minRTT,
189 uint16_t* maxRTT) const {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000190 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000191
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000192 RTCPReportBlockInformation* reportBlock =
193 GetReportBlockInformation(remoteSSRC);
194
195 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000196 return -1;
197 }
198 if (RTT) {
199 *RTT = reportBlock->RTT;
200 }
201 if (avgRTT) {
202 *avgRTT = reportBlock->avgRTT;
203 }
204 if (minRTT) {
205 *minRTT = reportBlock->minRTT;
206 }
207 if (maxRTT) {
208 *maxRTT = reportBlock->maxRTT;
209 }
210 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000211}
212
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000213bool RTCPReceiver::GetAndResetXrRrRtt(uint16_t* rtt_ms) {
214 assert(rtt_ms);
215 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
216 if (xr_rr_rtt_ms_ == 0) {
217 return false;
218 }
219 *rtt_ms = xr_rr_rtt_ms_;
220 xr_rr_rtt_ms_ = 0;
221 return true;
222}
223
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000224// TODO(pbos): Make this fail when we haven't received NTP.
225bool RTCPReceiver::NTP(uint32_t* ReceivedNTPsecs,
226 uint32_t* ReceivedNTPfrac,
227 uint32_t* RTCPArrivalTimeSecs,
228 uint32_t* RTCPArrivalTimeFrac,
229 uint32_t* rtcp_timestamp) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000230{
231 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
232 if(ReceivedNTPsecs)
233 {
234 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
235 }
236 if(ReceivedNTPfrac)
237 {
238 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
239 }
240 if(RTCPArrivalTimeFrac)
241 {
242 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
243 }
244 if(RTCPArrivalTimeSecs)
245 {
246 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
247 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000248 if (rtcp_timestamp) {
249 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
250 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000251 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000252}
253
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000254bool RTCPReceiver::LastReceivedXrReferenceTimeInfo(
255 RtcpReceiveTimeInfo* info) const {
256 assert(info);
257 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
258 if (_lastReceivedXRNTPsecs == 0 && _lastReceivedXRNTPfrac == 0) {
259 return false;
260 }
261
262 info->sourceSSRC = _remoteXRReceiveTimeInfo.sourceSSRC;
263 info->lastRR = _remoteXRReceiveTimeInfo.lastRR;
264
265 // Get the delay since last received report (RFC 3611).
266 uint32_t receive_time = RTCPUtility::MidNtp(_lastReceivedXRNTPsecs,
267 _lastReceivedXRNTPfrac);
268
269 uint32_t ntp_sec = 0;
270 uint32_t ntp_frac = 0;
271 _clock->CurrentNtp(ntp_sec, ntp_frac);
272 uint32_t now = RTCPUtility::MidNtp(ntp_sec, ntp_frac);
273
274 info->delaySinceLastRR = now - receive_time;
275 return true;
276}
277
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000278int32_t RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const {
279 assert(senderInfo);
280 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
281 if (_lastReceivedSRNTPsecs == 0) {
282 return -1;
283 }
284 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
285 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000286}
287
288// statistics
289// we can get multiple receive reports when we receive the report from a CE
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000290int32_t RTCPReceiver::StatisticsReceived(
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000291 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000292 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000293 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
294
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000295 std::map<uint32_t, RTCPReportBlockInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000296 _receivedReportBlockMap.begin();
297
298 while (it != _receivedReportBlockMap.end()) {
299 receiveBlocks->push_back(it->second->remoteReceiveBlock);
300 it++;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000301 }
302 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000303}
304
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000305void RTCPReceiver::GetPacketTypeCounter(
306 RtcpPacketTypeCounter* packet_counter) const {
307 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
308 *packet_counter = packet_type_counter_;
309}
310
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000311int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000312RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
313 RTCPUtility::RTCPParserV2* rtcpParser)
314{
315 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
316
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000317 _lastReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000318
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000319 if (packet_type_counter_.first_packet_time_ms == -1) {
320 packet_type_counter_.first_packet_time_ms = _lastReceived;
321 }
322
niklase@google.com470e71d2011-07-07 08:21:25 +0000323 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
324 while (pktType != RTCPUtility::kRtcpNotValidCode)
325 {
326 // Each "case" is responsible for iterate the parser to the
327 // next top level packet.
328 switch (pktType)
329 {
330 case RTCPUtility::kRtcpSrCode:
331 case RTCPUtility::kRtcpRrCode:
332 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
333 break;
334 case RTCPUtility::kRtcpSdesCode:
335 HandleSDES(*rtcpParser);
336 break;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000337 case RTCPUtility::kRtcpXrHeaderCode:
338 HandleXrHeader(*rtcpParser, rtcpPacketInformation);
339 break;
340 case RTCPUtility::kRtcpXrReceiverReferenceTimeCode:
341 HandleXrReceiveReferenceTime(*rtcpParser, rtcpPacketInformation);
342 break;
343 case RTCPUtility::kRtcpXrDlrrReportBlockCode:
344 HandleXrDlrrReportBlock(*rtcpParser, rtcpPacketInformation);
345 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000346 case RTCPUtility::kRtcpXrVoipMetricCode:
347 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
348 break;
349 case RTCPUtility::kRtcpByeCode:
350 HandleBYE(*rtcpParser);
351 break;
352 case RTCPUtility::kRtcpRtpfbNackCode:
353 HandleNACK(*rtcpParser, rtcpPacketInformation);
354 break;
355 case RTCPUtility::kRtcpRtpfbTmmbrCode:
356 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
357 break;
358 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000359 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000360 break;
361 case RTCPUtility::kRtcpRtpfbSrReqCode:
362 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
363 break;
364 case RTCPUtility::kRtcpPsfbPliCode:
365 HandlePLI(*rtcpParser, rtcpPacketInformation);
366 break;
367 case RTCPUtility::kRtcpPsfbSliCode:
368 HandleSLI(*rtcpParser, rtcpPacketInformation);
369 break;
370 case RTCPUtility::kRtcpPsfbRpsiCode:
371 HandleRPSI(*rtcpParser, rtcpPacketInformation);
372 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000373 case RTCPUtility::kRtcpExtendedIjCode:
374 HandleIJ(*rtcpParser, rtcpPacketInformation);
375 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000376 case RTCPUtility::kRtcpPsfbFirCode:
377 HandleFIR(*rtcpParser, rtcpPacketInformation);
378 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000379 case RTCPUtility::kRtcpPsfbAppCode:
380 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
381 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000382 case RTCPUtility::kRtcpAppCode:
383 // generic application messages
384 HandleAPP(*rtcpParser, rtcpPacketInformation);
385 break;
386 case RTCPUtility::kRtcpAppItemCode:
387 // generic application messages
388 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
389 break;
390 default:
391 rtcpParser->Iterate();
392 break;
393 }
394 pktType = rtcpParser->PacketType();
395 }
396 return 0;
397}
398
399// no need for critsect we have _criticalSectionRTCPReceiver
400void
401RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
402 RTCPPacketInformation& rtcpPacketInformation)
403{
404 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
405 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
406
407 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
408
409 // SR.SenderSSRC
410 // The synchronization source identifier for the originator of this SR packet
411
412 // rtcpPacket.RR.SenderSSRC
413 // The source of the packet sender, same as of SR? or is this a CE?
414
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000415 const uint32_t remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
416 const uint8_t numberOfReportBlocks = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.NumberOfReportBlocks:rtcpPacket.SR.NumberOfReportBlocks;
niklase@google.com470e71d2011-07-07 08:21:25 +0000417
418 rtcpPacketInformation.remoteSSRC = remoteSSRC;
419
420 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
421 if (!ptrReceiveInfo)
422 {
423 rtcpParser.Iterate();
424 return;
425 }
426
427 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
428 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000429 TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
430 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000431 "ssrc", main_ssrc_);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000432
niklase@google.com470e71d2011-07-07 08:21:25 +0000433 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
434 {
435 // only signal that we have received a SR when we accept one
436 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
437
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000438 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
439 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
440 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
441
niklase@google.com470e71d2011-07-07 08:21:25 +0000442 // We will only store the send report from one source, but
443 // we will store all the receive block
444
445 // Save the NTP time of this report
446 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
447 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
448 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
449 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
450 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
451
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000452 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000453 }
454 else
455 {
456 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
457 }
458 } else
459 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000460 TRACE_EVENT_INSTANT2("webrtc_rtp", "RR",
461 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000462 "ssrc", main_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000463
464 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
465 }
466 UpdateReceiveInformation(*ptrReceiveInfo);
467
468 rtcpPacketType = rtcpParser.Iterate();
469
470 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
471 {
472 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC, numberOfReportBlocks);
473 rtcpPacketType = rtcpParser.Iterate();
474 }
475}
476
477// no need for critsect we have _criticalSectionRTCPReceiver
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000478void RTCPReceiver::HandleReportBlock(
479 const RTCPUtility::RTCPPacket& rtcpPacket,
480 RTCPPacketInformation& rtcpPacketInformation,
481 const uint32_t remoteSSRC,
482 const uint8_t numberOfReportBlocks)
483 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000484 // This will be called once per report block in the RTCP packet.
485 // We filter out all report blocks that are not for us.
486 // Each packet has max 31 RR blocks.
487 //
488 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000489
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000490 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
491 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000492
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000493 // Filter out all report blocks that are not for us.
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000494 if (registered_ssrcs_.find(rtcpPacket.ReportBlockItem.SSRC) ==
495 registered_ssrcs_.end()) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000496 // This block is not for us ignore it.
497 return;
498 }
499
500 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
501 // _criticalSectionRTCPReceiver.
502 _criticalSectionRTCPReceiver->Leave();
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000503 uint32_t sendTimeMS =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000504 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
505 _criticalSectionRTCPReceiver->Enter();
506
507 RTCPReportBlockInformation* reportBlock =
508 CreateReportBlockInformation(remoteSSRC);
509 if (reportBlock == NULL) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000510 LOG(LS_WARNING) << "Failed to CreateReportBlockInformation("
511 << remoteSSRC << ")";
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000512 return;
513 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000514
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000515 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000516 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
517 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
518 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
519 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
520 reportBlock->remoteReceiveBlock.cumulativeLost =
521 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000522 if (rb.ExtendedHighestSequenceNumber >
523 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
524 // We have successfully delivered new RTP packets to the remote side after
525 // the last RR was sent from the remote side.
526 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000527 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000528 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
529 rb.ExtendedHighestSequenceNumber;
530 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
531 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
532 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
533
534 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
535 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
536 }
537
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000538 uint32_t delaySinceLastSendReport =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000539 rtcpPacket.ReportBlockItem.DelayLastSR;
540
541 // local NTP time when we received this
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000542 uint32_t lastReceivedRRNTPsecs = 0;
543 uint32_t lastReceivedRRNTPfrac = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000544
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000545 _clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000546
547 // time when we received this in MS
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000548 uint32_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
549 lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000550
551 // Estimate RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000552 uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000553 d /= 65536;
554 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
555
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000556 int32_t RTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000557
558 if (sendTimeMS > 0) {
559 RTT = receiveTimeMS - d - sendTimeMS;
560 if (RTT <= 0) {
561 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000562 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000563 if (RTT > reportBlock->maxRTT) {
564 // store max RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000565 reportBlock->maxRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000566 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000567 if (reportBlock->minRTT == 0) {
568 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000569 reportBlock->minRTT = (uint16_t) RTT;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000570 } else if (RTT < reportBlock->minRTT) {
571 // Store min RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000572 reportBlock->minRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000573 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000574 // store last RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000575 reportBlock->RTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000576
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000577 // store average RTT
578 if (reportBlock->numAverageCalcs != 0) {
579 float ac = static_cast<float> (reportBlock->numAverageCalcs);
580 float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT)
581 + ((1 / (ac + 1)) * RTT);
582 reportBlock->avgRTT = static_cast<int> (newAverage + 0.5f);
583 } else {
584 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000585 reportBlock->avgRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000586 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000587 reportBlock->numAverageCalcs++;
588 }
589
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000590 TRACE_COUNTER_ID1("webrtc_rtp", "RR_RTT", rb.SSRC, RTT);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000591
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000592 rtcpPacketInformation.AddReportInfo(*reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000593}
594
595RTCPReportBlockInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000596RTCPReceiver::CreateReportBlockInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000597 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000598
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000599 std::map<uint32_t, RTCPReportBlockInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000600 _receivedReportBlockMap.find(remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000601
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000602 RTCPReportBlockInformation* ptrReportBlockInfo = NULL;
603 if (it != _receivedReportBlockMap.end()) {
604 ptrReportBlockInfo = it->second;
605 } else {
606 ptrReportBlockInfo = new RTCPReportBlockInformation;
607 _receivedReportBlockMap[remoteSSRC] = ptrReportBlockInfo;
608 }
609 return ptrReportBlockInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000610}
611
612RTCPReportBlockInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000613RTCPReceiver::GetReportBlockInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000614 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000615
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000616 std::map<uint32_t, RTCPReportBlockInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000617 _receivedReportBlockMap.find(remoteSSRC);
618
619 if (it == _receivedReportBlockMap.end()) {
620 return NULL;
621 }
622 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000623}
624
625RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000626RTCPReceiver::CreateCnameInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000627 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000628
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000629 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000630 _receivedCnameMap.find(remoteSSRC);
631
632 if (it != _receivedCnameMap.end()) {
633 return it->second;
634 }
635 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000636 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000637 _receivedCnameMap[remoteSSRC] = cnameInfo;
638 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000639}
640
641RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000642RTCPReceiver::GetCnameInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000643 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000644
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000645 std::map<uint32_t, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000646 _receivedCnameMap.find(remoteSSRC);
647
648 if (it == _receivedCnameMap.end()) {
649 return NULL;
650 }
651 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000652}
653
654RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000655RTCPReceiver::CreateReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000656 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000657
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000658 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000659 _receivedInfoMap.find(remoteSSRC);
660
661 if (it != _receivedInfoMap.end()) {
662 return it->second;
663 }
664 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
665 _receivedInfoMap[remoteSSRC] = receiveInfo;
666 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000667}
668
669RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000670RTCPReceiver::GetReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000671 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000672
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000673 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000674 _receivedInfoMap.find(remoteSSRC);
675 if (it == _receivedInfoMap.end()) {
676 return NULL;
677 }
678 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000679}
680
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000681void RTCPReceiver::UpdateReceiveInformation(
682 RTCPReceiveInformation& receiveInformation) {
683 // Update that this remote is alive
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000684 receiveInformation.lastTimeReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000685}
686
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000687bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
688 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
689 if (_lastReceivedRrMs == 0)
690 return false;
691
692 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000693 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000694 // Reset the timer to only trigger one log.
695 _lastReceivedRrMs = 0;
696 return true;
697 }
698 return false;
699}
700
701bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
702 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
703 if (_lastIncreasedSequenceNumberMs == 0)
704 return false;
705
706 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000707 if (_clock->TimeInMilliseconds() > _lastIncreasedSequenceNumberMs +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000708 time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000709 // Reset the timer to only trigger one log.
710 _lastIncreasedSequenceNumberMs = 0;
711 return true;
712 }
713 return false;
714}
715
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000716bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
717 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000718
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000719 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000720 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000721
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000722 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000723 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000724
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000725 while (receiveInfoIt != _receivedInfoMap.end()) {
726 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
727 if (receiveInfo == NULL) {
728 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000729 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000730 // time since last received rtcp packet
731 // when we dont have a lastTimeReceived and the object is marked
732 // readyForDelete it's removed from the map
733 if (receiveInfo->lastTimeReceived) {
734 /// use audio define since we don't know what interval the remote peer is
735 // using
736 if ((timeNow - receiveInfo->lastTimeReceived) >
737 5 * RTCP_INTERVAL_AUDIO_MS) {
738 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000739 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000740 // prevent that we call this over and over again
741 receiveInfo->lastTimeReceived = 0;
742 // send new TMMBN to all channels using the default codec
743 updateBoundingSet = true;
744 }
745 receiveInfoIt++;
746 } else if (receiveInfo->readyForDelete) {
747 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000748 std::map<uint32_t, RTCPReceiveInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000749 receiveInfoItemToBeErased = receiveInfoIt;
750 receiveInfoIt++;
751 delete receiveInfoItemToBeErased->second;
752 _receivedInfoMap.erase(receiveInfoItemToBeErased);
753 } else {
754 receiveInfoIt++;
755 }
756 }
757 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000758}
759
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000760int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000761 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000762
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000763 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000764 _receivedInfoMap.find(_remoteSSRC);
765
766 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000767 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000768 }
769 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
770 if (receiveInfo == NULL) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000771 return -1;
772 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000773 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000774 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000775 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000776 for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000777 i++) {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000778 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000779 // owner of bounding set
780 tmmbrOwner = true;
781 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000782 boundingSetRec->SetEntry(i,
783 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
784 receiveInfo->TmmbnBoundingSet.PacketOH(i),
785 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000786 }
787 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000788 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000789}
790
791// no need for critsect we have _criticalSectionRTCPReceiver
792void
793RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser)
794{
795 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
796 while (pktType == RTCPUtility::kRtcpSdesChunkCode)
797 {
798 HandleSDESChunk(rtcpParser);
799 pktType = rtcpParser.Iterate();
800 }
801}
802
803// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000804void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
805 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
806 RTCPCnameInformation* cnameInfo =
807 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
808 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000809
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000810 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
811 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000812 if (stats_callback_ != NULL) {
813 stats_callback_->CNameChanged(rtcpPacket.CName.CName,
814 rtcpPacket.CName.SenderSSRC);
815 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000816}
817
818// no need for critsect we have _criticalSectionRTCPReceiver
819void
820RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
821 RTCPPacketInformation& rtcpPacketInformation)
822{
823 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000824 if (main_ssrc_ != rtcpPacket.NACK.MediaSSRC)
niklase@google.com470e71d2011-07-07 08:21:25 +0000825 {
826 // Not to us.
827 rtcpParser.Iterate();
828 return;
829 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000830 rtcpPacketInformation.ResetNACKPacketIdArray();
831
832 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
833 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode)
834 {
835 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
836 pktType = rtcpParser.Iterate();
837 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000838
839 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
840 ++packet_type_counter_.nack_packets;
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000841 packet_type_counter_.nack_requests = nack_stats_.requests();
842 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000843 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000844}
845
846// no need for critsect we have _criticalSectionRTCPReceiver
847void
848RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
849 RTCPPacketInformation& rtcpPacketInformation)
850{
851 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000852 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000853
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000854 uint16_t bitMask = rtcpPacket.NACKItem.BitMask;
niklase@google.com470e71d2011-07-07 08:21:25 +0000855 if(bitMask)
856 {
857 for(int i=1; i <= 16; ++i)
858 {
859 if(bitMask & 0x01)
860 {
861 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000862 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID + i);
niklase@google.com470e71d2011-07-07 08:21:25 +0000863 }
864 bitMask = bitMask >>1;
865 }
866 }
867
868 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
869}
870
871// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000872void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
873 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000874
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000875 // clear our lists
876 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000877 std::map<uint32_t, RTCPReportBlockInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000878 reportBlockInfoIt = _receivedReportBlockMap.find(
879 rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000880
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000881 if (reportBlockInfoIt != _receivedReportBlockMap.end()) {
882 delete reportBlockInfoIt->second;
883 _receivedReportBlockMap.erase(reportBlockInfoIt);
884 }
885 // we can't delete it due to TMMBR
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000886 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000887 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000888
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000889 if (receiveInfoIt != _receivedInfoMap.end()) {
890 receiveInfoIt->second->readyForDelete = true;
891 }
892
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000893 std::map<uint32_t, RTCPCnameInformation*>::iterator cnameInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000894 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
895
896 if (cnameInfoIt != _receivedCnameMap.end()) {
897 delete cnameInfoIt->second;
898 _receivedCnameMap.erase(cnameInfoIt);
899 }
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000900 xr_rr_rtt_ms_ = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000901 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000902}
903
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000904void RTCPReceiver::HandleXrHeader(
905 RTCPUtility::RTCPParserV2& parser,
906 RTCPPacketInformation& rtcpPacketInformation) {
907 const RTCPUtility::RTCPPacket& packet = parser.Packet();
908
909 rtcpPacketInformation.xr_originator_ssrc = packet.XR.OriginatorSSRC;
910
911 parser.Iterate();
912}
913
914void RTCPReceiver::HandleXrReceiveReferenceTime(
915 RTCPUtility::RTCPParserV2& parser,
916 RTCPPacketInformation& rtcpPacketInformation) {
917 const RTCPUtility::RTCPPacket& packet = parser.Packet();
918
919 _remoteXRReceiveTimeInfo.sourceSSRC =
920 rtcpPacketInformation.xr_originator_ssrc;
921
922 _remoteXRReceiveTimeInfo.lastRR = RTCPUtility::MidNtp(
923 packet.XRReceiverReferenceTimeItem.NTPMostSignificant,
924 packet.XRReceiverReferenceTimeItem.NTPLeastSignificant);
925
926 _clock->CurrentNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);
927
928 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
929
930 parser.Iterate();
931}
932
933void RTCPReceiver::HandleXrDlrrReportBlock(
934 RTCPUtility::RTCPParserV2& parser,
935 RTCPPacketInformation& rtcpPacketInformation) {
936 const RTCPUtility::RTCPPacket& packet = parser.Packet();
937 // Iterate through sub-block(s), if any.
938 RTCPUtility::RTCPPacketTypes packet_type = parser.Iterate();
939
940 while (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
941 HandleXrDlrrReportBlockItem(packet, rtcpPacketInformation);
942 packet_type = parser.Iterate();
943 }
944}
945
946void RTCPReceiver::HandleXrDlrrReportBlockItem(
947 const RTCPUtility::RTCPPacket& packet,
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000948 RTCPPacketInformation& rtcpPacketInformation)
949 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000950 if (registered_ssrcs_.find(packet.XRDLRRReportBlockItem.SSRC) ==
951 registered_ssrcs_.end()) {
952 // Not to us.
953 return;
954 }
955
956 rtcpPacketInformation.xr_dlrr_item = true;
957
958 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
959 // _criticalSectionRTCPReceiver.
960 _criticalSectionRTCPReceiver->Leave();
961
962 int64_t send_time_ms;
963 bool found = _rtpRtcp.SendTimeOfXrRrReport(
964 packet.XRDLRRReportBlockItem.LastRR, &send_time_ms);
965
966 _criticalSectionRTCPReceiver->Enter();
967
968 if (!found) {
969 return;
970 }
971
972 // The DelayLastRR field is in units of 1/65536 sec.
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000973 uint32_t delay_rr_ms =
974 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0x0000ffff) * 1000) >> 16) +
975 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0xffff0000) >> 16) * 1000);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000976
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000977 int32_t rtt = _clock->CurrentNtpInMilliseconds() - delay_rr_ms - send_time_ms;
978
979 xr_rr_rtt_ms_ = static_cast<uint16_t>(std::max(rtt, 1));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000980
981 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
982}
983
niklase@google.com470e71d2011-07-07 08:21:25 +0000984// no need for critsect we have _criticalSectionRTCPReceiver
985void
986RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
987 RTCPPacketInformation& rtcpPacketInformation)
988{
989 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
990
991 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
992
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000993 if(rtcpPacket.XRVOIPMetricItem.SSRC == main_ssrc_)
niklase@google.com470e71d2011-07-07 08:21:25 +0000994 {
995 // Store VoIP metrics block if it's about me
996 // from OriginatorSSRC do we filter it?
997 // rtcpPacket.XR.OriginatorSSRC;
998
999 RTCPVoIPMetric receivedVoIPMetrics;
1000 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
1001 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
1002 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
1003 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
1004 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
1005 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
1006 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
1007 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
1008 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
1009 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
1010 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
1011 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
1012 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
1013 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
1014 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
1015 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
1016 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
1017 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
1018 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
1019 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
1020
1021 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
1022
1023 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
1024 }
1025 rtcpParser.Iterate();
1026}
1027
1028// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001029void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
1030 RTCPPacketInformation& rtcpPacketInformation) {
1031 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001032 if (main_ssrc_ == rtcpPacket.PLI.MediaSSRC) {
justinlin@chromium.org7bfb3a32013-05-13 22:59:00 +00001033 TRACE_EVENT_INSTANT0("webrtc_rtp", "PLI");
1034
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001035 ++packet_type_counter_.pli_packets;
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001036 // Received a signal that we need to send a new key frame.
1037 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
1038 }
1039 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001040}
1041
1042// no need for critsect we have _criticalSectionRTCPReceiver
1043void
1044RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
1045 RTCPPacketInformation& rtcpPacketInformation)
1046{
1047 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1048
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001049 uint32_t senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001050 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
1051 if (ptrReceiveInfo == NULL)
1052 {
1053 // This remote SSRC must be saved before.
1054 rtcpParser.Iterate();
1055 return;
1056 }
1057 if(rtcpPacket.TMMBR.MediaSSRC)
1058 {
1059 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
1060 // in relay mode this is a valid number
1061 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
1062 }
1063
1064 // Use packet length to calc max number of TMMBR blocks
1065 // each TMMBR block is 8 bytes
1066 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
1067
1068 // sanity
1069 if(maxNumOfTMMBRBlocks > 200) // we can't have more than what's in one packet
1070 {
1071 assert(false);
1072 rtcpParser.Iterate();
1073 return;
1074 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001075 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((uint32_t)maxNumOfTMMBRBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001076
1077 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1078 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode)
1079 {
1080 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
1081 pktType = rtcpParser.Iterate();
1082 }
1083}
1084
1085// no need for critsect we have _criticalSectionRTCPReceiver
1086void
1087RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
1088 const RTCPUtility::RTCPPacket& rtcpPacket,
1089 RTCPPacketInformation& rtcpPacketInformation,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001090 const uint32_t senderSSRC)
niklase@google.com470e71d2011-07-07 08:21:25 +00001091{
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001092 if (main_ssrc_ == rtcpPacket.TMMBRItem.SSRC &&
niklase@google.com470e71d2011-07-07 08:21:25 +00001093 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
1094 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001095 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001096 _clock->TimeInMilliseconds());
niklase@google.com470e71d2011-07-07 08:21:25 +00001097 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
1098 }
1099}
1100
1101// no need for critsect we have _criticalSectionRTCPReceiver
1102void
hta@webrtc.org9d54cd12012-04-30 08:24:55 +00001103RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
1104 RTCPPacketInformation& rtcpPacketInformation)
niklase@google.com470e71d2011-07-07 08:21:25 +00001105{
1106 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1107 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.TMMBN.SenderSSRC);
1108 if (ptrReceiveInfo == NULL)
1109 {
1110 // This remote SSRC must be saved before.
1111 rtcpParser.Iterate();
1112 return;
1113 }
hta@webrtc.org9d54cd12012-04-30 08:24:55 +00001114 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +00001115 // Use packet length to calc max number of TMMBN blocks
1116 // each TMMBN block is 8 bytes
1117 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
1118
1119 // sanity
1120 if(maxNumOfTMMBNBlocks > 200) // we cant have more than what's in one packet
1121 {
1122 assert(false);
1123 rtcpParser.Iterate();
1124 return;
1125 }
1126
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001127 ptrReceiveInfo->VerifyAndAllocateBoundingSet((uint32_t)maxNumOfTMMBNBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001128
1129 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1130 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode)
1131 {
1132 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
1133 pktType = rtcpParser.Iterate();
1134 }
1135}
1136
1137// no need for critsect we have _criticalSectionRTCPReceiver
1138void
1139RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
1140 RTCPPacketInformation& rtcpPacketInformation)
1141{
1142 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
1143 rtcpParser.Iterate();
1144}
1145
1146// no need for critsect we have _criticalSectionRTCPReceiver
1147void
1148RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
1149 const RTCPUtility::RTCPPacket& rtcpPacket)
1150{
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001151 receiveInfo.TmmbnBoundingSet.AddEntry(
1152 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
1153 rtcpPacket.TMMBNItem.MeasuredOverhead,
1154 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001155}
1156
1157// no need for critsect we have _criticalSectionRTCPReceiver
1158void
1159RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
1160 RTCPPacketInformation& rtcpPacketInformation)
1161{
1162 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001163 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1164 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode)
1165 {
1166 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1167 pktType = rtcpParser.Iterate();
1168 }
1169}
1170
1171// no need for critsect we have _criticalSectionRTCPReceiver
1172void
1173RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1174 RTCPPacketInformation& rtcpPacketInformation)
1175{
1176 // in theory there could be multiple slices lost
1177 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1178 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
1179}
1180
1181void
1182RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1183 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1184{
1185 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001186 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1187 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1188 {
1189 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1190 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1191 {
1192 // to us unknown
1193 // continue
1194 rtcpParser.Iterate();
1195 return;
1196 }
1197 rtcpPacketInformation.rpsiPictureId = 0;
1198
1199 // convert NativeBitString to rpsiPictureId
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001200 uint8_t numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1201 for(uint8_t n = 0; n < (numberOfBytes-1); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001202 {
1203 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1204 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1205 }
1206 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1207 }
1208}
1209
1210// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001211void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1212 RTCPPacketInformation& rtcpPacketInformation) {
1213 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1214 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1215 pktType = rtcpParser.Iterate();
1216 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1217 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1218 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001219 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001220 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001221}
1222
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001223// no need for critsect we have _criticalSectionRTCPReceiver
1224void
1225RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1226 RTCPPacketInformation& rtcpPacketInformation)
1227{
1228 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1229
1230 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1231 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode)
1232 {
1233 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1234 pktType = rtcpParser.Iterate();
1235 }
1236}
1237
1238void
1239RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1240 RTCPPacketInformation& rtcpPacketInformation)
1241{
1242 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1243 rtcpPacketInformation.interArrivalJitter =
1244 rtcpPacket.ExtendedJitterReportItem.Jitter;
1245}
1246
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001247void RTCPReceiver::HandleREMBItem(
1248 RTCPUtility::RTCPParserV2& rtcpParser,
1249 RTCPPacketInformation& rtcpPacketInformation) {
1250 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1251 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1252 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1253 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001254}
1255
1256// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001257void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1258 RTCPPacketInformation& rtcpPacketInformation) {
1259 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1260 RTCPReceiveInformation* ptrReceiveInfo =
1261 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001262
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001263 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1264 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1265 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1266 pktType = rtcpParser.Iterate();
1267 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001268}
1269
1270// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001271void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1272 const RTCPUtility::RTCPPacket& rtcpPacket,
1273 RTCPPacketInformation& rtcpPacketInformation) {
1274 // Is it our sender that is requested to generate a new keyframe
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001275 if (main_ssrc_ != rtcpPacket.FIRItem.SSRC) {
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001276 return;
1277 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001278
1279 ++packet_type_counter_.fir_packets;
1280
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001281 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1282 // we don't know who this originate from
1283 if (receiveInfo) {
1284 // check if we have reported this FIRSequenceNumber before
1285 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1286 receiveInfo->lastFIRSequenceNumber) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001287 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001288 // sanity; don't go crazy with the callbacks
1289 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1290 receiveInfo->lastFIRRequest = now;
1291 receiveInfo->lastFIRSequenceNumber =
1292 rtcpPacket.FIRItem.CommandSequenceNumber;
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 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001297 } else {
1298 // received signal that we need to send a new key frame
1299 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1300 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001301}
1302
1303void
1304RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1305 RTCPPacketInformation& rtcpPacketInformation)
1306{
1307 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1308
1309 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1310 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1311 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
1312
1313 rtcpParser.Iterate();
1314}
1315
1316void
1317RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1318 RTCPPacketInformation& rtcpPacketInformation)
1319{
1320 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1321
1322 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
1323
1324 rtcpParser.Iterate();
1325}
1326
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001327int32_t RTCPReceiver::UpdateTMMBR() {
1328 int32_t numBoundingSet = 0;
1329 uint32_t bitrate = 0;
1330 uint32_t accNumCandidates = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001331
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001332 int32_t size = TMMBRReceived(0, 0, NULL);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001333 if (size > 0) {
1334 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1335 // Get candidate set from receiver.
1336 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1337 } else {
1338 // Candidate set empty.
1339 VerifyAndAllocateCandidateSet(0); // resets candidate set
1340 }
1341 // Find bounding set
1342 TMMBRSet* boundingSet = NULL;
1343 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1344 if (numBoundingSet == -1) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001345 LOG(LS_WARNING) << "Failed to find TMMBR bounding set.";
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001346 return -1;
1347 }
1348 // Set bounding set
1349 // Inform remote clients about the new bandwidth
1350 // inform the remote client
1351 _rtpRtcp.SetTMMBN(boundingSet);
1352
1353 // might trigger a TMMBN
1354 if (numBoundingSet == 0) {
1355 // owner of max bitrate request has timed out
1356 // empty bounding set has been sent
1357 return 0;
1358 }
1359 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001360 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001361 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001362 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1363 if (_cbRtcpBandwidthObserver) {
1364 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001365 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001366 }
1367 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001368}
1369
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001370void RTCPReceiver::RegisterRtcpStatisticsCallback(
1371 RtcpStatisticsCallback* callback) {
1372 CriticalSectionScoped cs(_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001373 stats_callback_ = callback;
1374}
1375
1376RtcpStatisticsCallback* RTCPReceiver::GetRtcpStatisticsCallback() {
1377 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1378 return stats_callback_;
1379}
1380
niklase@google.com470e71d2011-07-07 08:21:25 +00001381// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001382void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001383 RTCPPacketInformation& rtcpPacketInformation) {
1384 // Process TMMBR and REMB first to avoid multiple callbacks
1385 // to OnNetworkChanged.
1386 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001387 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1388 UpdateTMMBR();
1389 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001390 unsigned int local_ssrc = 0;
1391 {
1392 // We don't want to hold this critsect when triggering the callbacks below.
1393 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001394 local_ssrc = main_ssrc_;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001395 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001396 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1397 _rtpRtcp.OnRequestSendReport();
1398 }
1399 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001400 if (rtcpPacketInformation.nackSequenceNumbers.size() > 0) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001401 LOG(LS_VERBOSE) << "Incoming NACK length: "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001402 << rtcpPacketInformation.nackSequenceNumbers.size();
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001403 _rtpRtcp.OnReceivedNACK(rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001404 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001405 }
1406 {
1407 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001408
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001409 // We need feedback that we have received a report block(s) so that we
1410 // can generate a new packet in a conference relay scenario, one received
1411 // report can generate several RTCP packets, based on number relayed/mixed
1412 // a send report block should go out to all receivers.
1413 if (_cbRtcpIntraFrameObserver) {
1414 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1415 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1416 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001417 LOG(LS_VERBOSE) << "Incoming PLI from SSRC "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001418 << rtcpPacketInformation.remoteSSRC;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001419 } else {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001420 LOG(LS_VERBOSE) << "Incoming FIR from SSRC "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001421 << rtcpPacketInformation.remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001422 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001423 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001424 }
1425 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1426 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001427 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001428 }
1429 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1430 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001431 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001432 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001433 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001434 if (_cbRtcpBandwidthObserver) {
1435 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001436 LOG(LS_VERBOSE) << "Incoming REMB: "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001437 << rtcpPacketInformation.receiverEstimatedMaxBitrate;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001438 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1439 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1440 }
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001441 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1442 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001443 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001444 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001445 rtcpPacketInformation.report_blocks,
1446 rtcpPacketInformation.rtt,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001447 now);
1448 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001449 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001450 }
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001451
1452 {
1453 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1454 if (stats_callback_) {
1455 for (ReportBlockList::const_iterator it =
1456 rtcpPacketInformation.report_blocks.begin();
1457 it != rtcpPacketInformation.report_blocks.end();
1458 ++it) {
1459 RtcpStatistics stats;
1460 stats.cumulative_lost = it->cumulativeLost;
1461 stats.extended_max_sequence_number = it->extendedHighSeqNum;
1462 stats.fraction_lost = it->fractionLost;
1463 stats.jitter = it->jitter;
1464
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001465 stats_callback_->StatisticsUpdated(stats, it->sourceSSRC);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001466 }
1467 }
1468 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001469}
1470
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001471int32_t RTCPReceiver::CNAME(const uint32_t remoteSSRC,
1472 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001473 assert(cName);
1474
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001475 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1476 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001477 if (cnameInfo == NULL) {
1478 return -1;
1479 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001480 cName[RTCP_CNAME_SIZE - 1] = 0;
1481 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1482 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001483}
1484
1485// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001486int32_t RTCPReceiver::TMMBRReceived(const uint32_t size,
1487 const uint32_t accNumCandidates,
1488 TMMBRSet* candidateSet) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001489 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001490
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001491 std::map<uint32_t, RTCPReceiveInformation*>::const_iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001492 receiveInfoIt = _receivedInfoMap.begin();
1493 if (receiveInfoIt == _receivedInfoMap.end()) {
1494 return -1;
1495 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001496 uint32_t num = accNumCandidates;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001497 if (candidateSet) {
1498 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1499 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1500 if (receiveInfo == NULL) {
1501 return 0;
1502 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001503 for (uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001504 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001505 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001506 _clock->TimeInMilliseconds()) == 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001507 num++;
1508 }
1509 }
1510 receiveInfoIt++;
1511 }
1512 } else {
1513 while (receiveInfoIt != _receivedInfoMap.end()) {
1514 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1515 if(receiveInfo == NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001516 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001517 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001518 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001519 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001520 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001521 }
1522 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001523}
1524
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001525} // namespace webrtc