blob: 95ba287b5b5a1e4635844f339ef804569c42d5ad [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_receiver.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> //assert
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000014#include <string.h> //memset
niklase@google.com470e71d2011-07-07 08:21:25 +000015
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000016#include <algorithm>
17
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000018#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
19#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
20#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000021#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000022#include "webrtc/system_wrappers/interface/trace_event.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000023
niklase@google.com470e71d2011-07-07 08:21:25 +000024namespace webrtc {
25using namespace RTCPUtility;
26using namespace RTCPHelp;
27
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000028// The number of RTCP time intervals needed to trigger a timeout.
29const int kRrTimeoutIntervals = 3;
30
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000031RTCPReceiver::RTCPReceiver(int32_t id, Clock* clock, ModuleRtpRtcpImpl* owner)
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000032 : TMMBRHelp(),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000033 _id(id),
34 _clock(clock),
35 _method(kRtcpOff),
36 _lastReceived(0),
37 _rtpRtcp(*owner),
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000038 _criticalSectionFeedbacks(
39 CriticalSectionWrapper::CreateCriticalSection()),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000040 _cbRtcpBandwidthObserver(NULL),
41 _cbRtcpIntraFrameObserver(NULL),
42 _criticalSectionRTCPReceiver(
43 CriticalSectionWrapper::CreateCriticalSection()),
44 main_ssrc_(0),
45 _remoteSSRC(0),
46 _remoteSenderInfo(),
47 _lastReceivedSRNTPsecs(0),
48 _lastReceivedSRNTPfrac(0),
49 _lastReceivedXRNTPsecs(0),
50 _lastReceivedXRNTPfrac(0),
51 xr_rr_rtt_ms_(0),
52 _receivedInfoMap(),
53 _packetTimeOutMS(0),
54 _lastReceivedRrMs(0),
55 _lastIncreasedSequenceNumberMs(0),
56 stats_callback_(NULL) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +000057 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
niklase@google.com470e71d2011-07-07 08:21:25 +000058}
59
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000060RTCPReceiver::~RTCPReceiver() {
61 delete _criticalSectionRTCPReceiver;
62 delete _criticalSectionFeedbacks;
niklase@google.com470e71d2011-07-07 08:21:25 +000063
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +000064 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
65 for (; it != _receivedReportBlockMap.end(); ++it) {
66 ReportBlockInfoMap* info_map = &(it->second);
67 while (!info_map->empty()) {
68 ReportBlockInfoMap::iterator it_info = info_map->begin();
69 delete it_info->second;
70 info_map->erase(it_info);
71 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000072 }
73 while (!_receivedInfoMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000074 std::map<uint32_t, RTCPReceiveInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000075 _receivedInfoMap.begin();
76 delete first->second;
77 _receivedInfoMap.erase(first);
78 }
79 while (!_receivedCnameMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000080 std::map<uint32_t, RTCPCnameInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000081 _receivedCnameMap.begin();
82 delete first->second;
83 _receivedCnameMap.erase(first);
84 }
niklase@google.com470e71d2011-07-07 08:21:25 +000085}
86
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000087void RTCPReceiver::ChangeUniqueId(int32_t id) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +000088 _id = id;
niklase@google.com470e71d2011-07-07 08:21:25 +000089}
90
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +000091RTCPMethod RTCPReceiver::Status() const {
92 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
93 return _method;
niklase@google.com470e71d2011-07-07 08:21:25 +000094}
95
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000096void RTCPReceiver::SetRTCPStatus(RTCPMethod method) {
97 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
98 _method = method;
niklase@google.com470e71d2011-07-07 08:21:25 +000099}
100
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000101int64_t RTCPReceiver::LastReceived() {
102 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
103 return _lastReceived;
niklase@google.com470e71d2011-07-07 08:21:25 +0000104}
105
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000106int64_t RTCPReceiver::LastReceivedReceiverReport() const {
107 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
108 int64_t last_received_rr = -1;
109 for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin();
110 it != _receivedInfoMap.end(); ++it) {
111 if (it->second->lastTimeReceived > last_received_rr) {
112 last_received_rr = it->second->lastTimeReceived;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000113 }
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000114 }
115 return last_received_rr;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000116}
117
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000118void RTCPReceiver::SetRemoteSSRC(uint32_t ssrc) {
119 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000120
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000121 // new SSRC reset old reports
122 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
123 _lastReceivedSRNTPsecs = 0;
124 _lastReceivedSRNTPfrac = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000125
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000126 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000127}
128
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000129uint32_t RTCPReceiver::RemoteSSRC() const {
130 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
131 return _remoteSSRC;
132}
133
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000134void RTCPReceiver::RegisterRtcpObservers(
135 RtcpIntraFrameObserver* intra_frame_callback,
pbos@webrtc.orgece38902014-11-14 11:52:04 +0000136 RtcpBandwidthObserver* bandwidth_callback) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000137 CriticalSectionScoped lock(_criticalSectionFeedbacks);
138 _cbRtcpIntraFrameObserver = intra_frame_callback;
139 _cbRtcpBandwidthObserver = bandwidth_callback;
niklase@google.com470e71d2011-07-07 08:21:25 +0000140}
141
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000142void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
143 const std::set<uint32_t>& registered_ssrcs) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000144 uint32_t old_ssrc = 0;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000145 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000146 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000147 old_ssrc = main_ssrc_;
148 main_ssrc_ = main_ssrc;
149 registered_ssrcs_ = registered_ssrcs;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000150 }
151 {
152 CriticalSectionScoped lock(_criticalSectionFeedbacks);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000153 if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) {
154 _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc);
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000155 }
156 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000157}
158
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000159int32_t RTCPReceiver::RTT(uint32_t remoteSSRC,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000160 int64_t* RTT,
161 int64_t* avgRTT,
162 int64_t* minRTT,
163 int64_t* maxRTT) const {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000164 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000165
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000166 RTCPReportBlockInformation* reportBlock =
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000167 GetReportBlockInformation(remoteSSRC, main_ssrc_);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000168
169 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000170 return -1;
171 }
172 if (RTT) {
173 *RTT = reportBlock->RTT;
174 }
175 if (avgRTT) {
176 *avgRTT = reportBlock->avgRTT;
177 }
178 if (minRTT) {
179 *minRTT = reportBlock->minRTT;
180 }
181 if (maxRTT) {
182 *maxRTT = reportBlock->maxRTT;
183 }
184 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000185}
186
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000187bool RTCPReceiver::GetAndResetXrRrRtt(int64_t* rtt_ms) {
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000188 assert(rtt_ms);
189 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
190 if (xr_rr_rtt_ms_ == 0) {
191 return false;
192 }
193 *rtt_ms = xr_rr_rtt_ms_;
194 xr_rr_rtt_ms_ = 0;
195 return true;
196}
197
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000198// TODO(pbos): Make this fail when we haven't received NTP.
199bool RTCPReceiver::NTP(uint32_t* ReceivedNTPsecs,
200 uint32_t* ReceivedNTPfrac,
201 uint32_t* RTCPArrivalTimeSecs,
202 uint32_t* RTCPArrivalTimeFrac,
203 uint32_t* rtcp_timestamp) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000204{
205 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
206 if(ReceivedNTPsecs)
207 {
208 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
209 }
210 if(ReceivedNTPfrac)
211 {
212 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
213 }
214 if(RTCPArrivalTimeFrac)
215 {
216 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
217 }
218 if(RTCPArrivalTimeSecs)
219 {
220 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
221 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000222 if (rtcp_timestamp) {
223 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
224 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000225 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000226}
227
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000228bool RTCPReceiver::LastReceivedXrReferenceTimeInfo(
229 RtcpReceiveTimeInfo* info) const {
230 assert(info);
231 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
232 if (_lastReceivedXRNTPsecs == 0 && _lastReceivedXRNTPfrac == 0) {
233 return false;
234 }
235
236 info->sourceSSRC = _remoteXRReceiveTimeInfo.sourceSSRC;
237 info->lastRR = _remoteXRReceiveTimeInfo.lastRR;
238
239 // Get the delay since last received report (RFC 3611).
240 uint32_t receive_time = RTCPUtility::MidNtp(_lastReceivedXRNTPsecs,
241 _lastReceivedXRNTPfrac);
242
243 uint32_t ntp_sec = 0;
244 uint32_t ntp_frac = 0;
245 _clock->CurrentNtp(ntp_sec, ntp_frac);
246 uint32_t now = RTCPUtility::MidNtp(ntp_sec, ntp_frac);
247
248 info->delaySinceLastRR = now - receive_time;
249 return true;
250}
251
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000252int32_t RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const {
253 assert(senderInfo);
254 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
255 if (_lastReceivedSRNTPsecs == 0) {
256 return -1;
257 }
258 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
259 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000260}
261
262// statistics
263// we can get multiple receive reports when we receive the report from a CE
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000264int32_t RTCPReceiver::StatisticsReceived(
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000265 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000266 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000267 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000268 ReportBlockMap::const_iterator it = _receivedReportBlockMap.begin();
269 for (; it != _receivedReportBlockMap.end(); ++it) {
270 const ReportBlockInfoMap* info_map = &(it->second);
271 ReportBlockInfoMap::const_iterator it_info = info_map->begin();
272 for (; it_info != info_map->end(); ++it_info) {
273 receiveBlocks->push_back(it_info->second->remoteReceiveBlock);
274 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000275 }
276 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000277}
278
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000279void RTCPReceiver::GetPacketTypeCounter(
280 RtcpPacketTypeCounter* packet_counter) const {
281 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
282 *packet_counter = packet_type_counter_;
283}
284
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000285int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000286RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
287 RTCPUtility::RTCPParserV2* rtcpParser)
288{
289 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
290
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000291 _lastReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000292
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000293 if (packet_type_counter_.first_packet_time_ms == -1) {
294 packet_type_counter_.first_packet_time_ms = _lastReceived;
295 }
296
niklase@google.com470e71d2011-07-07 08:21:25 +0000297 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
298 while (pktType != RTCPUtility::kRtcpNotValidCode)
299 {
300 // Each "case" is responsible for iterate the parser to the
301 // next top level packet.
302 switch (pktType)
303 {
304 case RTCPUtility::kRtcpSrCode:
305 case RTCPUtility::kRtcpRrCode:
306 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
307 break;
308 case RTCPUtility::kRtcpSdesCode:
309 HandleSDES(*rtcpParser);
310 break;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000311 case RTCPUtility::kRtcpXrHeaderCode:
312 HandleXrHeader(*rtcpParser, rtcpPacketInformation);
313 break;
314 case RTCPUtility::kRtcpXrReceiverReferenceTimeCode:
315 HandleXrReceiveReferenceTime(*rtcpParser, rtcpPacketInformation);
316 break;
317 case RTCPUtility::kRtcpXrDlrrReportBlockCode:
318 HandleXrDlrrReportBlock(*rtcpParser, rtcpPacketInformation);
319 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000320 case RTCPUtility::kRtcpXrVoipMetricCode:
321 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
322 break;
323 case RTCPUtility::kRtcpByeCode:
324 HandleBYE(*rtcpParser);
325 break;
326 case RTCPUtility::kRtcpRtpfbNackCode:
327 HandleNACK(*rtcpParser, rtcpPacketInformation);
328 break;
329 case RTCPUtility::kRtcpRtpfbTmmbrCode:
330 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
331 break;
332 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000333 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000334 break;
335 case RTCPUtility::kRtcpRtpfbSrReqCode:
336 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
337 break;
338 case RTCPUtility::kRtcpPsfbPliCode:
339 HandlePLI(*rtcpParser, rtcpPacketInformation);
340 break;
341 case RTCPUtility::kRtcpPsfbSliCode:
342 HandleSLI(*rtcpParser, rtcpPacketInformation);
343 break;
344 case RTCPUtility::kRtcpPsfbRpsiCode:
345 HandleRPSI(*rtcpParser, rtcpPacketInformation);
346 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000347 case RTCPUtility::kRtcpExtendedIjCode:
348 HandleIJ(*rtcpParser, rtcpPacketInformation);
349 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000350 case RTCPUtility::kRtcpPsfbFirCode:
351 HandleFIR(*rtcpParser, rtcpPacketInformation);
352 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000353 case RTCPUtility::kRtcpPsfbAppCode:
354 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
355 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000356 case RTCPUtility::kRtcpAppCode:
357 // generic application messages
358 HandleAPP(*rtcpParser, rtcpPacketInformation);
359 break;
360 case RTCPUtility::kRtcpAppItemCode:
361 // generic application messages
362 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
363 break;
364 default:
365 rtcpParser->Iterate();
366 break;
367 }
368 pktType = rtcpParser->PacketType();
369 }
370 return 0;
371}
372
373// no need for critsect we have _criticalSectionRTCPReceiver
374void
375RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
376 RTCPPacketInformation& rtcpPacketInformation)
377{
378 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
379 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
380
381 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
382
383 // SR.SenderSSRC
384 // The synchronization source identifier for the originator of this SR packet
385
386 // rtcpPacket.RR.SenderSSRC
387 // The source of the packet sender, same as of SR? or is this a CE?
388
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000389 const uint32_t remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +0000390
391 rtcpPacketInformation.remoteSSRC = remoteSSRC;
392
393 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
394 if (!ptrReceiveInfo)
395 {
396 rtcpParser.Iterate();
397 return;
398 }
399
400 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
401 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000402 TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
403 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000404 "ssrc", main_ssrc_);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000405
niklase@google.com470e71d2011-07-07 08:21:25 +0000406 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
407 {
408 // only signal that we have received a SR when we accept one
409 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
410
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000411 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
412 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
413 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
414
niklase@google.com470e71d2011-07-07 08:21:25 +0000415 // We will only store the send report from one source, but
416 // we will store all the receive block
417
418 // Save the NTP time of this report
419 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
420 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
421 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
422 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
423 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
424
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000425 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000426 }
427 else
428 {
429 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
430 }
431 } else
432 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000433 TRACE_EVENT_INSTANT2("webrtc_rtp", "RR",
434 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000435 "ssrc", main_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000436
437 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
438 }
439 UpdateReceiveInformation(*ptrReceiveInfo);
440
441 rtcpPacketType = rtcpParser.Iterate();
442
443 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
444 {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000445 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000446 rtcpPacketType = rtcpParser.Iterate();
447 }
448}
449
450// no need for critsect we have _criticalSectionRTCPReceiver
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000451void RTCPReceiver::HandleReportBlock(
452 const RTCPUtility::RTCPPacket& rtcpPacket,
453 RTCPPacketInformation& rtcpPacketInformation,
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000454 uint32_t remoteSSRC)
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000455 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000456 // This will be called once per report block in the RTCP packet.
457 // We filter out all report blocks that are not for us.
458 // Each packet has max 31 RR blocks.
459 //
460 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000461
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000462 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
463 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000464
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000465 // Filter out all report blocks that are not for us.
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000466 if (registered_ssrcs_.find(rtcpPacket.ReportBlockItem.SSRC) ==
467 registered_ssrcs_.end()) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000468 // This block is not for us ignore it.
469 return;
470 }
471
472 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
473 // _criticalSectionRTCPReceiver.
474 _criticalSectionRTCPReceiver->Leave();
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000475 int64_t sendTimeMS =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000476 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
477 _criticalSectionRTCPReceiver->Enter();
478
479 RTCPReportBlockInformation* reportBlock =
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000480 CreateOrGetReportBlockInformation(remoteSSRC,
481 rtcpPacket.ReportBlockItem.SSRC);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000482 if (reportBlock == NULL) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000483 LOG(LS_WARNING) << "Failed to CreateReportBlockInformation("
484 << remoteSSRC << ")";
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000485 return;
486 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000487
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000488 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000489 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
490 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
491 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
492 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
493 reportBlock->remoteReceiveBlock.cumulativeLost =
494 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000495 if (rb.ExtendedHighestSequenceNumber >
496 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
497 // We have successfully delivered new RTP packets to the remote side after
498 // the last RR was sent from the remote side.
499 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000500 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000501 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
502 rb.ExtendedHighestSequenceNumber;
503 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
504 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
505 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
506
507 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
508 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
509 }
510
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000511 uint32_t delaySinceLastSendReport =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000512 rtcpPacket.ReportBlockItem.DelayLastSR;
513
514 // local NTP time when we received this
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000515 uint32_t lastReceivedRRNTPsecs = 0;
516 uint32_t lastReceivedRRNTPfrac = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000517
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000518 _clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000519
520 // time when we received this in MS
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000521 int64_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
522 lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000523
524 // Estimate RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000525 uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000526 d /= 65536;
527 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
528
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000529 int64_t RTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000530
531 if (sendTimeMS > 0) {
532 RTT = receiveTimeMS - d - sendTimeMS;
533 if (RTT <= 0) {
534 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000535 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000536 if (RTT > reportBlock->maxRTT) {
537 // store max RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000538 reportBlock->maxRTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000539 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000540 if (reportBlock->minRTT == 0) {
541 // first RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000542 reportBlock->minRTT = RTT;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000543 } else if (RTT < reportBlock->minRTT) {
544 // Store min RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000545 reportBlock->minRTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000546 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000547 // store last RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000548 reportBlock->RTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000549
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000550 // store average RTT
551 if (reportBlock->numAverageCalcs != 0) {
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000552 float ac = static_cast<float>(reportBlock->numAverageCalcs);
553 float newAverage =
554 ((ac / (ac + 1)) * reportBlock->avgRTT) + ((1 / (ac + 1)) * RTT);
555 reportBlock->avgRTT = static_cast<int64_t>(newAverage + 0.5f);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000556 } else {
557 // first RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000558 reportBlock->avgRTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000559 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000560 reportBlock->numAverageCalcs++;
561 }
562
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000563 TRACE_COUNTER_ID1("webrtc_rtp", "RR_RTT", rb.SSRC, RTT);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000564
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000565 rtcpPacketInformation.AddReportInfo(*reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000566}
567
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000568RTCPReportBlockInformation* RTCPReceiver::CreateOrGetReportBlockInformation(
569 uint32_t remote_ssrc,
570 uint32_t source_ssrc) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000571 RTCPReportBlockInformation* info =
572 GetReportBlockInformation(remote_ssrc, source_ssrc);
573 if (info == NULL) {
574 info = new RTCPReportBlockInformation;
575 _receivedReportBlockMap[source_ssrc][remote_ssrc] = info;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000576 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000577 return info;
niklase@google.com470e71d2011-07-07 08:21:25 +0000578}
579
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000580RTCPReportBlockInformation* RTCPReceiver::GetReportBlockInformation(
581 uint32_t remote_ssrc,
582 uint32_t source_ssrc) const {
583 ReportBlockMap::const_iterator it = _receivedReportBlockMap.find(source_ssrc);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000584 if (it == _receivedReportBlockMap.end()) {
585 return NULL;
586 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000587 const ReportBlockInfoMap* info_map = &(it->second);
588 ReportBlockInfoMap::const_iterator it_info = info_map->find(remote_ssrc);
589 if (it_info == info_map->end()) {
590 return NULL;
591 }
592 return it_info->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000593}
594
595RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000596RTCPReceiver::CreateCnameInformation(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, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000600 _receivedCnameMap.find(remoteSSRC);
601
602 if (it != _receivedCnameMap.end()) {
603 return it->second;
604 }
605 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000606 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000607 _receivedCnameMap[remoteSSRC] = cnameInfo;
608 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000609}
610
611RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000612RTCPReceiver::GetCnameInformation(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, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000616 _receivedCnameMap.find(remoteSSRC);
617
618 if (it == _receivedCnameMap.end()) {
619 return NULL;
620 }
621 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000622}
623
624RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000625RTCPReceiver::CreateReceiveInformation(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, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000629 _receivedInfoMap.find(remoteSSRC);
630
631 if (it != _receivedInfoMap.end()) {
632 return it->second;
633 }
634 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
635 _receivedInfoMap[remoteSSRC] = receiveInfo;
636 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000637}
638
639RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000640RTCPReceiver::GetReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000641 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000642
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000643 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000644 _receivedInfoMap.find(remoteSSRC);
645 if (it == _receivedInfoMap.end()) {
646 return NULL;
647 }
648 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000649}
650
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000651void RTCPReceiver::UpdateReceiveInformation(
652 RTCPReceiveInformation& receiveInformation) {
653 // Update that this remote is alive
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000654 receiveInformation.lastTimeReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000655}
656
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000657bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
658 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
659 if (_lastReceivedRrMs == 0)
660 return false;
661
662 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000663 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000664 // Reset the timer to only trigger one log.
665 _lastReceivedRrMs = 0;
666 return true;
667 }
668 return false;
669}
670
671bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
672 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
673 if (_lastIncreasedSequenceNumberMs == 0)
674 return false;
675
676 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000677 if (_clock->TimeInMilliseconds() > _lastIncreasedSequenceNumberMs +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000678 time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000679 // Reset the timer to only trigger one log.
680 _lastIncreasedSequenceNumberMs = 0;
681 return true;
682 }
683 return false;
684}
685
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000686bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
687 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000688
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000689 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000690 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000691
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000692 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000693 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000694
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000695 while (receiveInfoIt != _receivedInfoMap.end()) {
696 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
697 if (receiveInfo == NULL) {
698 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000699 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000700 // time since last received rtcp packet
701 // when we dont have a lastTimeReceived and the object is marked
702 // readyForDelete it's removed from the map
703 if (receiveInfo->lastTimeReceived) {
704 /// use audio define since we don't know what interval the remote peer is
705 // using
706 if ((timeNow - receiveInfo->lastTimeReceived) >
707 5 * RTCP_INTERVAL_AUDIO_MS) {
708 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000709 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000710 // prevent that we call this over and over again
711 receiveInfo->lastTimeReceived = 0;
712 // send new TMMBN to all channels using the default codec
713 updateBoundingSet = true;
714 }
715 receiveInfoIt++;
716 } else if (receiveInfo->readyForDelete) {
717 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000718 std::map<uint32_t, RTCPReceiveInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000719 receiveInfoItemToBeErased = receiveInfoIt;
720 receiveInfoIt++;
721 delete receiveInfoItemToBeErased->second;
722 _receivedInfoMap.erase(receiveInfoItemToBeErased);
723 } else {
724 receiveInfoIt++;
725 }
726 }
727 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000728}
729
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000730int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000731 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000732
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000733 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000734 _receivedInfoMap.find(_remoteSSRC);
735
736 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000737 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000738 }
739 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
740 if (receiveInfo == NULL) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000741 return -1;
742 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000743 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000744 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000745 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000746 for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000747 i++) {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000748 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000749 // owner of bounding set
750 tmmbrOwner = true;
751 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000752 boundingSetRec->SetEntry(i,
753 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
754 receiveInfo->TmmbnBoundingSet.PacketOH(i),
755 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000756 }
757 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000758 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000759}
760
761// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000762void RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser) {
763 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
764 while (pktType == RTCPUtility::kRtcpSdesChunkCode) {
765 HandleSDESChunk(rtcpParser);
766 pktType = rtcpParser.Iterate();
767 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000768}
769
770// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000771void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
772 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
773 RTCPCnameInformation* cnameInfo =
774 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
775 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000776
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000777 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
778 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000779 if (stats_callback_ != NULL) {
780 stats_callback_->CNameChanged(rtcpPacket.CName.CName,
781 rtcpPacket.CName.SenderSSRC);
782 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000783}
784
785// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000786void RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
787 RTCPPacketInformation& rtcpPacketInformation) {
788 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
789 if (main_ssrc_ != rtcpPacket.NACK.MediaSSRC) {
790 // Not to us.
791 rtcpParser.Iterate();
792 return;
793 }
794 rtcpPacketInformation.ResetNACKPacketIdArray();
niklase@google.com470e71d2011-07-07 08:21:25 +0000795
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000796 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
797 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode) {
798 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
799 pktType = rtcpParser.Iterate();
800 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000801
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000802 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
803 ++packet_type_counter_.nack_packets;
804 packet_type_counter_.nack_requests = nack_stats_.requests();
805 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
806 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000807}
808
809// no need for critsect we have _criticalSectionRTCPReceiver
810void
811RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000812 RTCPPacketInformation& rtcpPacketInformation) {
813 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
814 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000815
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000816 uint16_t bitMask = rtcpPacket.NACKItem.BitMask;
817 if (bitMask) {
818 for (int i=1; i <= 16; ++i) {
819 if (bitMask & 0x01) {
820 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
821 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID + i);
822 }
823 bitMask = bitMask >>1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000824 }
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000825 }
826 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
niklase@google.com470e71d2011-07-07 08:21:25 +0000827}
828
829// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000830void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
831 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000832
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000833 // clear our lists
834 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000835 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
836 for (; it != _receivedReportBlockMap.end(); ++it) {
837 ReportBlockInfoMap* info_map = &(it->second);
838 ReportBlockInfoMap::iterator it_info = info_map->find(
839 rtcpPacket.BYE.SenderSSRC);
840 if (it_info != info_map->end()) {
841 delete it_info->second;
842 info_map->erase(it_info);
843 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000844 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000845
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000846 // we can't delete it due to TMMBR
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000847 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000848 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000849
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000850 if (receiveInfoIt != _receivedInfoMap.end()) {
851 receiveInfoIt->second->readyForDelete = true;
852 }
853
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000854 std::map<uint32_t, RTCPCnameInformation*>::iterator cnameInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000855 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
856
857 if (cnameInfoIt != _receivedCnameMap.end()) {
858 delete cnameInfoIt->second;
859 _receivedCnameMap.erase(cnameInfoIt);
860 }
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000861 xr_rr_rtt_ms_ = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000862 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000863}
864
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000865void RTCPReceiver::HandleXrHeader(
866 RTCPUtility::RTCPParserV2& parser,
867 RTCPPacketInformation& rtcpPacketInformation) {
868 const RTCPUtility::RTCPPacket& packet = parser.Packet();
869
870 rtcpPacketInformation.xr_originator_ssrc = packet.XR.OriginatorSSRC;
871
872 parser.Iterate();
873}
874
875void RTCPReceiver::HandleXrReceiveReferenceTime(
876 RTCPUtility::RTCPParserV2& parser,
877 RTCPPacketInformation& rtcpPacketInformation) {
878 const RTCPUtility::RTCPPacket& packet = parser.Packet();
879
880 _remoteXRReceiveTimeInfo.sourceSSRC =
881 rtcpPacketInformation.xr_originator_ssrc;
882
883 _remoteXRReceiveTimeInfo.lastRR = RTCPUtility::MidNtp(
884 packet.XRReceiverReferenceTimeItem.NTPMostSignificant,
885 packet.XRReceiverReferenceTimeItem.NTPLeastSignificant);
886
887 _clock->CurrentNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);
888
889 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
890
891 parser.Iterate();
892}
893
894void RTCPReceiver::HandleXrDlrrReportBlock(
895 RTCPUtility::RTCPParserV2& parser,
896 RTCPPacketInformation& rtcpPacketInformation) {
897 const RTCPUtility::RTCPPacket& packet = parser.Packet();
898 // Iterate through sub-block(s), if any.
899 RTCPUtility::RTCPPacketTypes packet_type = parser.Iterate();
900
901 while (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
902 HandleXrDlrrReportBlockItem(packet, rtcpPacketInformation);
903 packet_type = parser.Iterate();
904 }
905}
906
907void RTCPReceiver::HandleXrDlrrReportBlockItem(
908 const RTCPUtility::RTCPPacket& packet,
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000909 RTCPPacketInformation& rtcpPacketInformation)
910 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000911 if (registered_ssrcs_.find(packet.XRDLRRReportBlockItem.SSRC) ==
912 registered_ssrcs_.end()) {
913 // Not to us.
914 return;
915 }
916
917 rtcpPacketInformation.xr_dlrr_item = true;
918
919 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
920 // _criticalSectionRTCPReceiver.
921 _criticalSectionRTCPReceiver->Leave();
922
923 int64_t send_time_ms;
924 bool found = _rtpRtcp.SendTimeOfXrRrReport(
925 packet.XRDLRRReportBlockItem.LastRR, &send_time_ms);
926
927 _criticalSectionRTCPReceiver->Enter();
928
929 if (!found) {
930 return;
931 }
932
933 // The DelayLastRR field is in units of 1/65536 sec.
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000934 uint32_t delay_rr_ms =
935 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0x0000ffff) * 1000) >> 16) +
936 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0xffff0000) >> 16) * 1000);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000937
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000938 int64_t rtt = _clock->CurrentNtpInMilliseconds() - delay_rr_ms - send_time_ms;
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000939
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000940 xr_rr_rtt_ms_ = std::max<int64_t>(rtt, 1);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000941
942 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
943}
944
niklase@google.com470e71d2011-07-07 08:21:25 +0000945// no need for critsect we have _criticalSectionRTCPReceiver
946void
947RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
948 RTCPPacketInformation& rtcpPacketInformation)
949{
950 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
951
952 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
953
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000954 if(rtcpPacket.XRVOIPMetricItem.SSRC == main_ssrc_)
niklase@google.com470e71d2011-07-07 08:21:25 +0000955 {
956 // Store VoIP metrics block if it's about me
957 // from OriginatorSSRC do we filter it?
958 // rtcpPacket.XR.OriginatorSSRC;
959
960 RTCPVoIPMetric receivedVoIPMetrics;
961 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
962 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
963 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
964 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
965 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
966 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
967 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
968 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
969 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
970 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
971 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
972 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
973 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
974 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
975 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
976 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
977 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
978 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
979 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
980 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
981
982 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
983
984 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
985 }
986 rtcpParser.Iterate();
987}
988
989// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000990void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
991 RTCPPacketInformation& rtcpPacketInformation) {
992 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000993 if (main_ssrc_ == rtcpPacket.PLI.MediaSSRC) {
justinlin@chromium.org7bfb3a32013-05-13 22:59:00 +0000994 TRACE_EVENT_INSTANT0("webrtc_rtp", "PLI");
995
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000996 ++packet_type_counter_.pli_packets;
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000997 // Received a signal that we need to send a new key frame.
998 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
999 }
1000 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001001}
1002
1003// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001004void RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
1005 RTCPPacketInformation& rtcpPacketInformation) {
1006 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001007
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001008 uint32_t senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
1009 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
1010 if (ptrReceiveInfo == NULL) {
1011 // This remote SSRC must be saved before.
1012 rtcpParser.Iterate();
1013 return;
1014 }
1015 if (rtcpPacket.TMMBR.MediaSSRC) {
1016 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
1017 // in relay mode this is a valid number
1018 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
1019 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001020
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001021 // Use packet length to calc max number of TMMBR blocks
1022 // each TMMBR block is 8 bytes
1023 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001024
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001025 // sanity, we can't have more than what's in one packet
1026 if (maxNumOfTMMBRBlocks > 200) {
1027 assert(false);
1028 rtcpParser.Iterate();
1029 return;
1030 }
1031 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((uint32_t)maxNumOfTMMBRBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001032
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001033 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1034 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode) {
1035 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
1036 pktType = rtcpParser.Iterate();
1037 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001038}
1039
1040// no need for critsect we have _criticalSectionRTCPReceiver
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001041void RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
1042 const RTCPUtility::RTCPPacket& rtcpPacket,
1043 RTCPPacketInformation& rtcpPacketInformation,
1044 uint32_t senderSSRC) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001045 if (main_ssrc_ == rtcpPacket.TMMBRItem.SSRC &&
1046 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0) {
1047 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
1048 _clock->TimeInMilliseconds());
1049 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
1050 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001051}
1052
1053// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001054void RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
1055 RTCPPacketInformation& rtcpPacketInformation) {
1056 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1057 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(
1058 rtcpPacket.TMMBN.SenderSSRC);
1059 if (ptrReceiveInfo == NULL) {
1060 // This remote SSRC must be saved before.
niklase@google.com470e71d2011-07-07 08:21:25 +00001061 rtcpParser.Iterate();
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001062 return;
1063 }
1064 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
1065 // Use packet length to calc max number of TMMBN blocks
1066 // each TMMBN block is 8 bytes
1067 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
1068
1069 // sanity, we cant have more than what's in one packet
1070 if (maxNumOfTMMBNBlocks > 200) {
1071 assert(false);
1072 rtcpParser.Iterate();
1073 return;
1074 }
1075
1076 ptrReceiveInfo->VerifyAndAllocateBoundingSet((uint32_t)maxNumOfTMMBNBlocks);
1077
1078 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1079 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode) {
1080 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
1081 pktType = rtcpParser.Iterate();
1082 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001083}
1084
1085// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001086void RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
1087 RTCPPacketInformation& rtcpPacketInformation) {
1088 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
1089 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001090}
1091
1092// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001093void RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
1094 const RTCPUtility::RTCPPacket& rtcpPacket) {
1095 receiveInfo.TmmbnBoundingSet.AddEntry(
1096 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
1097 rtcpPacket.TMMBNItem.MeasuredOverhead,
1098 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001099}
1100
1101// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001102void RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
1103 RTCPPacketInformation& rtcpPacketInformation) {
1104 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1105 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1106 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode) {
1107 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1108 pktType = rtcpParser.Iterate();
1109 }
1110}
1111
1112// no need for critsect we have _criticalSectionRTCPReceiver
1113void RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1114 RTCPPacketInformation& rtcpPacketInformation) {
1115 // in theory there could be multiple slices lost
1116 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1117 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
niklase@google.com470e71d2011-07-07 08:21:25 +00001118}
1119
1120void
1121RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1122 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1123{
1124 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001125 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1126 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1127 {
1128 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1129 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1130 {
1131 // to us unknown
1132 // continue
1133 rtcpParser.Iterate();
1134 return;
1135 }
1136 rtcpPacketInformation.rpsiPictureId = 0;
1137
1138 // convert NativeBitString to rpsiPictureId
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001139 uint8_t numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1140 for(uint8_t n = 0; n < (numberOfBytes-1); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001141 {
1142 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1143 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1144 }
1145 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1146 }
1147}
1148
1149// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001150void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1151 RTCPPacketInformation& rtcpPacketInformation) {
1152 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1153 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1154 pktType = rtcpParser.Iterate();
1155 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1156 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1157 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001158 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001159 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001160}
1161
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001162// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001163void RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1164 RTCPPacketInformation& rtcpPacketInformation) {
1165 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001166
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001167 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1168 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode) {
1169 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1170 pktType = rtcpParser.Iterate();
1171 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001172}
1173
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001174void RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1175 RTCPPacketInformation& rtcpPacketInformation) {
1176 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1177 rtcpPacketInformation.interArrivalJitter =
1178 rtcpPacket.ExtendedJitterReportItem.Jitter;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001179}
1180
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001181void RTCPReceiver::HandleREMBItem(
1182 RTCPUtility::RTCPParserV2& rtcpParser,
1183 RTCPPacketInformation& rtcpPacketInformation) {
1184 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1185 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1186 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1187 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001188}
1189
1190// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001191void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1192 RTCPPacketInformation& rtcpPacketInformation) {
1193 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1194 RTCPReceiveInformation* ptrReceiveInfo =
1195 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001196
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001197 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1198 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1199 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1200 pktType = rtcpParser.Iterate();
1201 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001202}
1203
1204// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001205void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1206 const RTCPUtility::RTCPPacket& rtcpPacket,
1207 RTCPPacketInformation& rtcpPacketInformation) {
1208 // Is it our sender that is requested to generate a new keyframe
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001209 if (main_ssrc_ != rtcpPacket.FIRItem.SSRC) {
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001210 return;
1211 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001212
1213 ++packet_type_counter_.fir_packets;
1214
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001215 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1216 // we don't know who this originate from
1217 if (receiveInfo) {
1218 // check if we have reported this FIRSequenceNumber before
1219 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1220 receiveInfo->lastFIRSequenceNumber) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001221 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001222 // sanity; don't go crazy with the callbacks
1223 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1224 receiveInfo->lastFIRRequest = now;
1225 receiveInfo->lastFIRSequenceNumber =
1226 rtcpPacket.FIRItem.CommandSequenceNumber;
1227 // received signal that we need to send a new key frame
1228 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1229 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001230 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001231 } else {
1232 // received signal that we need to send a new key frame
1233 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1234 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001235}
1236
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001237void RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1238 RTCPPacketInformation& rtcpPacketInformation) {
1239 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001240
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001241 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1242 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1243 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
niklase@google.com470e71d2011-07-07 08:21:25 +00001244
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001245 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001246}
1247
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001248void RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1249 RTCPPacketInformation& rtcpPacketInformation) {
1250 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001251
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001252 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
niklase@google.com470e71d2011-07-07 08:21:25 +00001253
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001254 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001255}
1256
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001257int32_t RTCPReceiver::UpdateTMMBR() {
1258 int32_t numBoundingSet = 0;
1259 uint32_t bitrate = 0;
1260 uint32_t accNumCandidates = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001261
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001262 int32_t size = TMMBRReceived(0, 0, NULL);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001263 if (size > 0) {
1264 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1265 // Get candidate set from receiver.
1266 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1267 } else {
1268 // Candidate set empty.
1269 VerifyAndAllocateCandidateSet(0); // resets candidate set
1270 }
1271 // Find bounding set
1272 TMMBRSet* boundingSet = NULL;
1273 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1274 if (numBoundingSet == -1) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001275 LOG(LS_WARNING) << "Failed to find TMMBR bounding set.";
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001276 return -1;
1277 }
1278 // Set bounding set
1279 // Inform remote clients about the new bandwidth
1280 // inform the remote client
1281 _rtpRtcp.SetTMMBN(boundingSet);
1282
1283 // might trigger a TMMBN
1284 if (numBoundingSet == 0) {
1285 // owner of max bitrate request has timed out
1286 // empty bounding set has been sent
1287 return 0;
1288 }
1289 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001290 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001291 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001292 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1293 if (_cbRtcpBandwidthObserver) {
1294 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001295 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001296 }
1297 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001298}
1299
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001300void RTCPReceiver::RegisterRtcpStatisticsCallback(
1301 RtcpStatisticsCallback* callback) {
1302 CriticalSectionScoped cs(_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001303 stats_callback_ = callback;
1304}
1305
1306RtcpStatisticsCallback* RTCPReceiver::GetRtcpStatisticsCallback() {
1307 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1308 return stats_callback_;
1309}
1310
niklase@google.com470e71d2011-07-07 08:21:25 +00001311// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001312void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001313 RTCPPacketInformation& rtcpPacketInformation) {
1314 // Process TMMBR and REMB first to avoid multiple callbacks
1315 // to OnNetworkChanged.
1316 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001317 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1318 UpdateTMMBR();
1319 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001320 unsigned int local_ssrc = 0;
1321 {
1322 // We don't want to hold this critsect when triggering the callbacks below.
1323 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001324 local_ssrc = main_ssrc_;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001325 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001326 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1327 _rtpRtcp.OnRequestSendReport();
1328 }
1329 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001330 if (rtcpPacketInformation.nackSequenceNumbers.size() > 0) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001331 LOG(LS_VERBOSE) << "Incoming NACK length: "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001332 << rtcpPacketInformation.nackSequenceNumbers.size();
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001333 _rtpRtcp.OnReceivedNACK(rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001334 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001335 }
1336 {
1337 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001338
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001339 // We need feedback that we have received a report block(s) so that we
1340 // can generate a new packet in a conference relay scenario, one received
1341 // report can generate several RTCP packets, based on number relayed/mixed
1342 // a send report block should go out to all receivers.
1343 if (_cbRtcpIntraFrameObserver) {
1344 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1345 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1346 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001347 LOG(LS_VERBOSE) << "Incoming PLI from SSRC "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001348 << rtcpPacketInformation.remoteSSRC;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001349 } else {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001350 LOG(LS_VERBOSE) << "Incoming FIR from SSRC "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001351 << rtcpPacketInformation.remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001352 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001353 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001354 }
1355 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1356 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001357 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001358 }
1359 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1360 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001361 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001362 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001363 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001364 if (_cbRtcpBandwidthObserver) {
1365 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001366 LOG(LS_VERBOSE) << "Incoming REMB: "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001367 << rtcpPacketInformation.receiverEstimatedMaxBitrate;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001368 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1369 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1370 }
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001371 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1372 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001373 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001374 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001375 rtcpPacketInformation.report_blocks,
1376 rtcpPacketInformation.rtt,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001377 now);
1378 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001379 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001380 }
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001381
1382 {
1383 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1384 if (stats_callback_) {
1385 for (ReportBlockList::const_iterator it =
1386 rtcpPacketInformation.report_blocks.begin();
1387 it != rtcpPacketInformation.report_blocks.end();
1388 ++it) {
1389 RtcpStatistics stats;
1390 stats.cumulative_lost = it->cumulativeLost;
1391 stats.extended_max_sequence_number = it->extendedHighSeqNum;
1392 stats.fraction_lost = it->fractionLost;
1393 stats.jitter = it->jitter;
1394
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001395 stats_callback_->StatisticsUpdated(stats, it->sourceSSRC);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001396 }
1397 }
1398 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001399}
1400
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001401int32_t RTCPReceiver::CNAME(uint32_t remoteSSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001402 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001403 assert(cName);
1404
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001405 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1406 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001407 if (cnameInfo == NULL) {
1408 return -1;
1409 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001410 cName[RTCP_CNAME_SIZE - 1] = 0;
1411 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1412 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001413}
1414
1415// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001416int32_t RTCPReceiver::TMMBRReceived(uint32_t size,
1417 uint32_t accNumCandidates,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001418 TMMBRSet* candidateSet) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001419 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001420
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001421 std::map<uint32_t, RTCPReceiveInformation*>::const_iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001422 receiveInfoIt = _receivedInfoMap.begin();
1423 if (receiveInfoIt == _receivedInfoMap.end()) {
1424 return -1;
1425 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001426 uint32_t num = accNumCandidates;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001427 if (candidateSet) {
1428 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1429 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1430 if (receiveInfo == NULL) {
1431 return 0;
1432 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001433 for (uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001434 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001435 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001436 _clock->TimeInMilliseconds()) == 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001437 num++;
1438 }
1439 }
1440 receiveInfoIt++;
1441 }
1442 } else {
1443 while (receiveInfoIt != _receivedInfoMap.end()) {
1444 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1445 if(receiveInfo == NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001446 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001447 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001448 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001449 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001450 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001451 }
1452 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001453}
1454
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001455} // namespace webrtc