blob: 8e5ac12372bdffe148e9ab329d3d3abc206a9a89 [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
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +000065 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
66 for (; it != _receivedReportBlockMap.end(); ++it) {
67 ReportBlockInfoMap* info_map = &(it->second);
68 while (!info_map->empty()) {
69 ReportBlockInfoMap::iterator it_info = info_map->begin();
70 delete it_info->second;
71 info_map->erase(it_info);
72 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000073 }
74 while (!_receivedInfoMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000075 std::map<uint32_t, RTCPReceiveInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000076 _receivedInfoMap.begin();
77 delete first->second;
78 _receivedInfoMap.erase(first);
79 }
80 while (!_receivedCnameMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000081 std::map<uint32_t, RTCPCnameInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000082 _receivedCnameMap.begin();
83 delete first->second;
84 _receivedCnameMap.erase(first);
85 }
niklase@google.com470e71d2011-07-07 08:21:25 +000086}
87
88void
pbos@webrtc.org2f446732013-04-08 11:08:41 +000089RTCPReceiver::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +000090{
91 _id = id;
92}
93
94RTCPMethod
95RTCPReceiver::Status() const
96{
97 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
98 return _method;
99}
100
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000101int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000102RTCPReceiver::SetRTCPStatus(const RTCPMethod method)
103{
104 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
105 _method = method;
106 return 0;
107}
108
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000109int64_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000110RTCPReceiver::LastReceived()
111{
112 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
113 return _lastReceived;
114}
115
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000116int64_t
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000117RTCPReceiver::LastReceivedReceiverReport() const {
118 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000119 int64_t last_received_rr = -1;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000120 for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin();
121 it != _receivedInfoMap.end(); ++it) {
122 if (it->second->lastTimeReceived > last_received_rr) {
123 last_received_rr = it->second->lastTimeReceived;
124 }
125 }
126 return last_received_rr;
127}
128
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000129int32_t
130RTCPReceiver::SetRemoteSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000131{
132 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
133
134 // new SSRC reset old reports
135 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
136 _lastReceivedSRNTPsecs = 0;
137 _lastReceivedSRNTPfrac = 0;
138
139 _remoteSSRC = ssrc;
140 return 0;
141}
142
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000143uint32_t RTCPReceiver::RemoteSSRC() const {
144 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
145 return _remoteSSRC;
146}
147
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000148void RTCPReceiver::RegisterRtcpObservers(
149 RtcpIntraFrameObserver* intra_frame_callback,
pbos@webrtc.orgece38902014-11-14 11:52:04 +0000150 RtcpBandwidthObserver* bandwidth_callback) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000151 CriticalSectionScoped lock(_criticalSectionFeedbacks);
152 _cbRtcpIntraFrameObserver = intra_frame_callback;
153 _cbRtcpBandwidthObserver = bandwidth_callback;
niklase@google.com470e71d2011-07-07 08:21:25 +0000154}
155
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000156void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
157 const std::set<uint32_t>& registered_ssrcs) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000158 uint32_t old_ssrc = 0;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000159 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000160 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000161 old_ssrc = main_ssrc_;
162 main_ssrc_ = main_ssrc;
163 registered_ssrcs_ = registered_ssrcs;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000164 }
165 {
166 CriticalSectionScoped lock(_criticalSectionFeedbacks);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000167 if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) {
168 _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc);
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000169 }
170 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000171}
172
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000173int32_t RTCPReceiver::RTT(uint32_t remoteSSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000174 uint16_t* RTT,
175 uint16_t* avgRTT,
176 uint16_t* minRTT,
177 uint16_t* maxRTT) const {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000178 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000179
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000180 RTCPReportBlockInformation* reportBlock =
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000181 GetReportBlockInformation(remoteSSRC, main_ssrc_);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000182
183 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000184 return -1;
185 }
186 if (RTT) {
187 *RTT = reportBlock->RTT;
188 }
189 if (avgRTT) {
190 *avgRTT = reportBlock->avgRTT;
191 }
192 if (minRTT) {
193 *minRTT = reportBlock->minRTT;
194 }
195 if (maxRTT) {
196 *maxRTT = reportBlock->maxRTT;
197 }
198 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000199}
200
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000201bool RTCPReceiver::GetAndResetXrRrRtt(uint16_t* rtt_ms) {
202 assert(rtt_ms);
203 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
204 if (xr_rr_rtt_ms_ == 0) {
205 return false;
206 }
207 *rtt_ms = xr_rr_rtt_ms_;
208 xr_rr_rtt_ms_ = 0;
209 return true;
210}
211
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000212// TODO(pbos): Make this fail when we haven't received NTP.
213bool RTCPReceiver::NTP(uint32_t* ReceivedNTPsecs,
214 uint32_t* ReceivedNTPfrac,
215 uint32_t* RTCPArrivalTimeSecs,
216 uint32_t* RTCPArrivalTimeFrac,
217 uint32_t* rtcp_timestamp) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000218{
219 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
220 if(ReceivedNTPsecs)
221 {
222 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
223 }
224 if(ReceivedNTPfrac)
225 {
226 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
227 }
228 if(RTCPArrivalTimeFrac)
229 {
230 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
231 }
232 if(RTCPArrivalTimeSecs)
233 {
234 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
235 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000236 if (rtcp_timestamp) {
237 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
238 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000239 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000240}
241
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000242bool RTCPReceiver::LastReceivedXrReferenceTimeInfo(
243 RtcpReceiveTimeInfo* info) const {
244 assert(info);
245 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
246 if (_lastReceivedXRNTPsecs == 0 && _lastReceivedXRNTPfrac == 0) {
247 return false;
248 }
249
250 info->sourceSSRC = _remoteXRReceiveTimeInfo.sourceSSRC;
251 info->lastRR = _remoteXRReceiveTimeInfo.lastRR;
252
253 // Get the delay since last received report (RFC 3611).
254 uint32_t receive_time = RTCPUtility::MidNtp(_lastReceivedXRNTPsecs,
255 _lastReceivedXRNTPfrac);
256
257 uint32_t ntp_sec = 0;
258 uint32_t ntp_frac = 0;
259 _clock->CurrentNtp(ntp_sec, ntp_frac);
260 uint32_t now = RTCPUtility::MidNtp(ntp_sec, ntp_frac);
261
262 info->delaySinceLastRR = now - receive_time;
263 return true;
264}
265
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000266int32_t RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const {
267 assert(senderInfo);
268 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
269 if (_lastReceivedSRNTPsecs == 0) {
270 return -1;
271 }
272 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
273 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000274}
275
276// statistics
277// we can get multiple receive reports when we receive the report from a CE
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000278int32_t RTCPReceiver::StatisticsReceived(
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000279 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000280 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000281 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000282 ReportBlockMap::const_iterator it = _receivedReportBlockMap.begin();
283 for (; it != _receivedReportBlockMap.end(); ++it) {
284 const ReportBlockInfoMap* info_map = &(it->second);
285 ReportBlockInfoMap::const_iterator it_info = info_map->begin();
286 for (; it_info != info_map->end(); ++it_info) {
287 receiveBlocks->push_back(it_info->second->remoteReceiveBlock);
288 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000289 }
290 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000291}
292
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000293void RTCPReceiver::GetPacketTypeCounter(
294 RtcpPacketTypeCounter* packet_counter) const {
295 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
296 *packet_counter = packet_type_counter_;
297}
298
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000299int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000300RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
301 RTCPUtility::RTCPParserV2* rtcpParser)
302{
303 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
304
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000305 _lastReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000306
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000307 if (packet_type_counter_.first_packet_time_ms == -1) {
308 packet_type_counter_.first_packet_time_ms = _lastReceived;
309 }
310
niklase@google.com470e71d2011-07-07 08:21:25 +0000311 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
312 while (pktType != RTCPUtility::kRtcpNotValidCode)
313 {
314 // Each "case" is responsible for iterate the parser to the
315 // next top level packet.
316 switch (pktType)
317 {
318 case RTCPUtility::kRtcpSrCode:
319 case RTCPUtility::kRtcpRrCode:
320 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
321 break;
322 case RTCPUtility::kRtcpSdesCode:
323 HandleSDES(*rtcpParser);
324 break;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000325 case RTCPUtility::kRtcpXrHeaderCode:
326 HandleXrHeader(*rtcpParser, rtcpPacketInformation);
327 break;
328 case RTCPUtility::kRtcpXrReceiverReferenceTimeCode:
329 HandleXrReceiveReferenceTime(*rtcpParser, rtcpPacketInformation);
330 break;
331 case RTCPUtility::kRtcpXrDlrrReportBlockCode:
332 HandleXrDlrrReportBlock(*rtcpParser, rtcpPacketInformation);
333 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000334 case RTCPUtility::kRtcpXrVoipMetricCode:
335 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
336 break;
337 case RTCPUtility::kRtcpByeCode:
338 HandleBYE(*rtcpParser);
339 break;
340 case RTCPUtility::kRtcpRtpfbNackCode:
341 HandleNACK(*rtcpParser, rtcpPacketInformation);
342 break;
343 case RTCPUtility::kRtcpRtpfbTmmbrCode:
344 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
345 break;
346 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000347 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000348 break;
349 case RTCPUtility::kRtcpRtpfbSrReqCode:
350 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
351 break;
352 case RTCPUtility::kRtcpPsfbPliCode:
353 HandlePLI(*rtcpParser, rtcpPacketInformation);
354 break;
355 case RTCPUtility::kRtcpPsfbSliCode:
356 HandleSLI(*rtcpParser, rtcpPacketInformation);
357 break;
358 case RTCPUtility::kRtcpPsfbRpsiCode:
359 HandleRPSI(*rtcpParser, rtcpPacketInformation);
360 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000361 case RTCPUtility::kRtcpExtendedIjCode:
362 HandleIJ(*rtcpParser, rtcpPacketInformation);
363 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000364 case RTCPUtility::kRtcpPsfbFirCode:
365 HandleFIR(*rtcpParser, rtcpPacketInformation);
366 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000367 case RTCPUtility::kRtcpPsfbAppCode:
368 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
369 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000370 case RTCPUtility::kRtcpAppCode:
371 // generic application messages
372 HandleAPP(*rtcpParser, rtcpPacketInformation);
373 break;
374 case RTCPUtility::kRtcpAppItemCode:
375 // generic application messages
376 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
377 break;
378 default:
379 rtcpParser->Iterate();
380 break;
381 }
382 pktType = rtcpParser->PacketType();
383 }
384 return 0;
385}
386
387// no need for critsect we have _criticalSectionRTCPReceiver
388void
389RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
390 RTCPPacketInformation& rtcpPacketInformation)
391{
392 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
393 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
394
395 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
396
397 // SR.SenderSSRC
398 // The synchronization source identifier for the originator of this SR packet
399
400 // rtcpPacket.RR.SenderSSRC
401 // The source of the packet sender, same as of SR? or is this a CE?
402
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000403 const uint32_t remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
404 const uint8_t numberOfReportBlocks = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.NumberOfReportBlocks:rtcpPacket.SR.NumberOfReportBlocks;
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
406 rtcpPacketInformation.remoteSSRC = remoteSSRC;
407
408 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
409 if (!ptrReceiveInfo)
410 {
411 rtcpParser.Iterate();
412 return;
413 }
414
415 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
416 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000417 TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
418 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000419 "ssrc", main_ssrc_);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000420
niklase@google.com470e71d2011-07-07 08:21:25 +0000421 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
422 {
423 // only signal that we have received a SR when we accept one
424 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
425
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000426 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
427 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
428 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
429
niklase@google.com470e71d2011-07-07 08:21:25 +0000430 // We will only store the send report from one source, but
431 // we will store all the receive block
432
433 // Save the NTP time of this report
434 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
435 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
436 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
437 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
438 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
439
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000440 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000441 }
442 else
443 {
444 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
445 }
446 } else
447 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000448 TRACE_EVENT_INSTANT2("webrtc_rtp", "RR",
449 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000450 "ssrc", main_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000451
452 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
453 }
454 UpdateReceiveInformation(*ptrReceiveInfo);
455
456 rtcpPacketType = rtcpParser.Iterate();
457
458 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
459 {
460 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC, numberOfReportBlocks);
461 rtcpPacketType = rtcpParser.Iterate();
462 }
463}
464
465// no need for critsect we have _criticalSectionRTCPReceiver
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000466void RTCPReceiver::HandleReportBlock(
467 const RTCPUtility::RTCPPacket& rtcpPacket,
468 RTCPPacketInformation& rtcpPacketInformation,
469 const uint32_t remoteSSRC,
470 const uint8_t numberOfReportBlocks)
471 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000472 // This will be called once per report block in the RTCP packet.
473 // We filter out all report blocks that are not for us.
474 // Each packet has max 31 RR blocks.
475 //
476 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000477
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000478 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
479 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000480
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000481 // Filter out all report blocks that are not for us.
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000482 if (registered_ssrcs_.find(rtcpPacket.ReportBlockItem.SSRC) ==
483 registered_ssrcs_.end()) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000484 // This block is not for us ignore it.
485 return;
486 }
487
488 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
489 // _criticalSectionRTCPReceiver.
490 _criticalSectionRTCPReceiver->Leave();
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000491 uint32_t sendTimeMS =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000492 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
493 _criticalSectionRTCPReceiver->Enter();
494
495 RTCPReportBlockInformation* reportBlock =
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000496 CreateOrGetReportBlockInformation(remoteSSRC,
497 rtcpPacket.ReportBlockItem.SSRC);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000498 if (reportBlock == NULL) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000499 LOG(LS_WARNING) << "Failed to CreateReportBlockInformation("
500 << remoteSSRC << ")";
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000501 return;
502 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000503
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000504 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000505 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
506 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
507 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
508 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
509 reportBlock->remoteReceiveBlock.cumulativeLost =
510 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000511 if (rb.ExtendedHighestSequenceNumber >
512 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
513 // We have successfully delivered new RTP packets to the remote side after
514 // the last RR was sent from the remote side.
515 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000516 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000517 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
518 rb.ExtendedHighestSequenceNumber;
519 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
520 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
521 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
522
523 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
524 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
525 }
526
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000527 uint32_t delaySinceLastSendReport =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000528 rtcpPacket.ReportBlockItem.DelayLastSR;
529
530 // local NTP time when we received this
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000531 uint32_t lastReceivedRRNTPsecs = 0;
532 uint32_t lastReceivedRRNTPfrac = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000533
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000534 _clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000535
536 // time when we received this in MS
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000537 uint32_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
538 lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000539
540 // Estimate RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000541 uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000542 d /= 65536;
543 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
544
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000545 int32_t RTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000546
547 if (sendTimeMS > 0) {
548 RTT = receiveTimeMS - d - sendTimeMS;
549 if (RTT <= 0) {
550 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000551 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000552 if (RTT > reportBlock->maxRTT) {
553 // store max RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000554 reportBlock->maxRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000555 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000556 if (reportBlock->minRTT == 0) {
557 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000558 reportBlock->minRTT = (uint16_t) RTT;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000559 } else if (RTT < reportBlock->minRTT) {
560 // Store min RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000561 reportBlock->minRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000562 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000563 // store last RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000564 reportBlock->RTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000565
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000566 // store average RTT
567 if (reportBlock->numAverageCalcs != 0) {
568 float ac = static_cast<float> (reportBlock->numAverageCalcs);
569 float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT)
570 + ((1 / (ac + 1)) * RTT);
571 reportBlock->avgRTT = static_cast<int> (newAverage + 0.5f);
572 } else {
573 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000574 reportBlock->avgRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000575 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000576 reportBlock->numAverageCalcs++;
577 }
578
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000579 TRACE_COUNTER_ID1("webrtc_rtp", "RR_RTT", rb.SSRC, RTT);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000580
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000581 rtcpPacketInformation.AddReportInfo(*reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000582}
583
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000584RTCPReportBlockInformation* RTCPReceiver::CreateOrGetReportBlockInformation(
585 uint32_t remote_ssrc,
586 uint32_t source_ssrc) {
587 ReportBlockMap::iterator it = _receivedReportBlockMap.find(source_ssrc);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000588 if (it != _receivedReportBlockMap.end()) {
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000589 ReportBlockInfoMap* info_map = &(it->second);
590 ReportBlockInfoMap::iterator it_info = info_map->find(remote_ssrc);
591 if (it_info != info_map->end()) {
592 return it_info->second;
593 }
594 RTCPReportBlockInformation* info = new RTCPReportBlockInformation;
595 (*info_map)[remote_ssrc] = info;
596 return info;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000597 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000598 RTCPReportBlockInformation* info = new RTCPReportBlockInformation;
599 _receivedReportBlockMap[source_ssrc][remote_ssrc] = info;
600 return info;
niklase@google.com470e71d2011-07-07 08:21:25 +0000601}
602
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000603RTCPReportBlockInformation* RTCPReceiver::GetReportBlockInformation(
604 uint32_t remote_ssrc,
605 uint32_t source_ssrc) const {
606 ReportBlockMap::const_iterator it = _receivedReportBlockMap.find(source_ssrc);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000607 if (it == _receivedReportBlockMap.end()) {
608 return NULL;
609 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000610 const ReportBlockInfoMap* info_map = &(it->second);
611 ReportBlockInfoMap::const_iterator it_info = info_map->find(remote_ssrc);
612 if (it_info == info_map->end()) {
613 return NULL;
614 }
615 return it_info->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000616}
617
618RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000619RTCPReceiver::CreateCnameInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000620 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000621
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000622 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000623 _receivedCnameMap.find(remoteSSRC);
624
625 if (it != _receivedCnameMap.end()) {
626 return it->second;
627 }
628 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000629 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000630 _receivedCnameMap[remoteSSRC] = cnameInfo;
631 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000632}
633
634RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000635RTCPReceiver::GetCnameInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000636 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000637
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000638 std::map<uint32_t, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000639 _receivedCnameMap.find(remoteSSRC);
640
641 if (it == _receivedCnameMap.end()) {
642 return NULL;
643 }
644 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000645}
646
647RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000648RTCPReceiver::CreateReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000649 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000650
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000651 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000652 _receivedInfoMap.find(remoteSSRC);
653
654 if (it != _receivedInfoMap.end()) {
655 return it->second;
656 }
657 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
658 _receivedInfoMap[remoteSSRC] = receiveInfo;
659 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000660}
661
662RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000663RTCPReceiver::GetReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000664 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000665
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000666 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000667 _receivedInfoMap.find(remoteSSRC);
668 if (it == _receivedInfoMap.end()) {
669 return NULL;
670 }
671 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000672}
673
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000674void RTCPReceiver::UpdateReceiveInformation(
675 RTCPReceiveInformation& receiveInformation) {
676 // Update that this remote is alive
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000677 receiveInformation.lastTimeReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000678}
679
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000680bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
681 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
682 if (_lastReceivedRrMs == 0)
683 return false;
684
685 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000686 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000687 // Reset the timer to only trigger one log.
688 _lastReceivedRrMs = 0;
689 return true;
690 }
691 return false;
692}
693
694bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
695 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
696 if (_lastIncreasedSequenceNumberMs == 0)
697 return false;
698
699 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000700 if (_clock->TimeInMilliseconds() > _lastIncreasedSequenceNumberMs +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000701 time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000702 // Reset the timer to only trigger one log.
703 _lastIncreasedSequenceNumberMs = 0;
704 return true;
705 }
706 return false;
707}
708
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000709bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
710 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000711
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000712 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000713 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000714
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000715 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000716 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000717
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000718 while (receiveInfoIt != _receivedInfoMap.end()) {
719 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
720 if (receiveInfo == NULL) {
721 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000722 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000723 // time since last received rtcp packet
724 // when we dont have a lastTimeReceived and the object is marked
725 // readyForDelete it's removed from the map
726 if (receiveInfo->lastTimeReceived) {
727 /// use audio define since we don't know what interval the remote peer is
728 // using
729 if ((timeNow - receiveInfo->lastTimeReceived) >
730 5 * RTCP_INTERVAL_AUDIO_MS) {
731 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000732 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000733 // prevent that we call this over and over again
734 receiveInfo->lastTimeReceived = 0;
735 // send new TMMBN to all channels using the default codec
736 updateBoundingSet = true;
737 }
738 receiveInfoIt++;
739 } else if (receiveInfo->readyForDelete) {
740 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000741 std::map<uint32_t, RTCPReceiveInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000742 receiveInfoItemToBeErased = receiveInfoIt;
743 receiveInfoIt++;
744 delete receiveInfoItemToBeErased->second;
745 _receivedInfoMap.erase(receiveInfoItemToBeErased);
746 } else {
747 receiveInfoIt++;
748 }
749 }
750 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000751}
752
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000753int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000754 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000755
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000756 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000757 _receivedInfoMap.find(_remoteSSRC);
758
759 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000760 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000761 }
762 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
763 if (receiveInfo == NULL) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000764 return -1;
765 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000766 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000767 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000768 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000769 for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000770 i++) {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000771 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000772 // owner of bounding set
773 tmmbrOwner = true;
774 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000775 boundingSetRec->SetEntry(i,
776 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
777 receiveInfo->TmmbnBoundingSet.PacketOH(i),
778 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000779 }
780 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000781 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000782}
783
784// no need for critsect we have _criticalSectionRTCPReceiver
785void
786RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser)
787{
788 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
789 while (pktType == RTCPUtility::kRtcpSdesChunkCode)
790 {
791 HandleSDESChunk(rtcpParser);
792 pktType = rtcpParser.Iterate();
793 }
794}
795
796// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000797void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
798 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
799 RTCPCnameInformation* cnameInfo =
800 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
801 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000802
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000803 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
804 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000805 if (stats_callback_ != NULL) {
806 stats_callback_->CNameChanged(rtcpPacket.CName.CName,
807 rtcpPacket.CName.SenderSSRC);
808 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000809}
810
811// no need for critsect we have _criticalSectionRTCPReceiver
812void
813RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
814 RTCPPacketInformation& rtcpPacketInformation)
815{
816 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000817 if (main_ssrc_ != rtcpPacket.NACK.MediaSSRC)
niklase@google.com470e71d2011-07-07 08:21:25 +0000818 {
819 // Not to us.
820 rtcpParser.Iterate();
821 return;
822 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000823 rtcpPacketInformation.ResetNACKPacketIdArray();
824
825 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
826 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode)
827 {
828 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
829 pktType = rtcpParser.Iterate();
830 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000831
832 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
833 ++packet_type_counter_.nack_packets;
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000834 packet_type_counter_.nack_requests = nack_stats_.requests();
835 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000836 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000837}
838
839// no need for critsect we have _criticalSectionRTCPReceiver
840void
841RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
842 RTCPPacketInformation& rtcpPacketInformation)
843{
844 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000845 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000846
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000847 uint16_t bitMask = rtcpPacket.NACKItem.BitMask;
niklase@google.com470e71d2011-07-07 08:21:25 +0000848 if(bitMask)
849 {
850 for(int i=1; i <= 16; ++i)
851 {
852 if(bitMask & 0x01)
853 {
854 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000855 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID + i);
niklase@google.com470e71d2011-07-07 08:21:25 +0000856 }
857 bitMask = bitMask >>1;
858 }
859 }
860
861 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
862}
863
864// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000865void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
866 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000867
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000868 // clear our lists
869 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000870 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
871 for (; it != _receivedReportBlockMap.end(); ++it) {
872 ReportBlockInfoMap* info_map = &(it->second);
873 ReportBlockInfoMap::iterator it_info = info_map->find(
874 rtcpPacket.BYE.SenderSSRC);
875 if (it_info != info_map->end()) {
876 delete it_info->second;
877 info_map->erase(it_info);
878 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000879 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000880
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000881 // we can't delete it due to TMMBR
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000882 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000883 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000884
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000885 if (receiveInfoIt != _receivedInfoMap.end()) {
886 receiveInfoIt->second->readyForDelete = true;
887 }
888
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000889 std::map<uint32_t, RTCPCnameInformation*>::iterator cnameInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000890 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
891
892 if (cnameInfoIt != _receivedCnameMap.end()) {
893 delete cnameInfoIt->second;
894 _receivedCnameMap.erase(cnameInfoIt);
895 }
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000896 xr_rr_rtt_ms_ = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000897 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000898}
899
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000900void RTCPReceiver::HandleXrHeader(
901 RTCPUtility::RTCPParserV2& parser,
902 RTCPPacketInformation& rtcpPacketInformation) {
903 const RTCPUtility::RTCPPacket& packet = parser.Packet();
904
905 rtcpPacketInformation.xr_originator_ssrc = packet.XR.OriginatorSSRC;
906
907 parser.Iterate();
908}
909
910void RTCPReceiver::HandleXrReceiveReferenceTime(
911 RTCPUtility::RTCPParserV2& parser,
912 RTCPPacketInformation& rtcpPacketInformation) {
913 const RTCPUtility::RTCPPacket& packet = parser.Packet();
914
915 _remoteXRReceiveTimeInfo.sourceSSRC =
916 rtcpPacketInformation.xr_originator_ssrc;
917
918 _remoteXRReceiveTimeInfo.lastRR = RTCPUtility::MidNtp(
919 packet.XRReceiverReferenceTimeItem.NTPMostSignificant,
920 packet.XRReceiverReferenceTimeItem.NTPLeastSignificant);
921
922 _clock->CurrentNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);
923
924 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
925
926 parser.Iterate();
927}
928
929void RTCPReceiver::HandleXrDlrrReportBlock(
930 RTCPUtility::RTCPParserV2& parser,
931 RTCPPacketInformation& rtcpPacketInformation) {
932 const RTCPUtility::RTCPPacket& packet = parser.Packet();
933 // Iterate through sub-block(s), if any.
934 RTCPUtility::RTCPPacketTypes packet_type = parser.Iterate();
935
936 while (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
937 HandleXrDlrrReportBlockItem(packet, rtcpPacketInformation);
938 packet_type = parser.Iterate();
939 }
940}
941
942void RTCPReceiver::HandleXrDlrrReportBlockItem(
943 const RTCPUtility::RTCPPacket& packet,
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000944 RTCPPacketInformation& rtcpPacketInformation)
945 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000946 if (registered_ssrcs_.find(packet.XRDLRRReportBlockItem.SSRC) ==
947 registered_ssrcs_.end()) {
948 // Not to us.
949 return;
950 }
951
952 rtcpPacketInformation.xr_dlrr_item = true;
953
954 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
955 // _criticalSectionRTCPReceiver.
956 _criticalSectionRTCPReceiver->Leave();
957
958 int64_t send_time_ms;
959 bool found = _rtpRtcp.SendTimeOfXrRrReport(
960 packet.XRDLRRReportBlockItem.LastRR, &send_time_ms);
961
962 _criticalSectionRTCPReceiver->Enter();
963
964 if (!found) {
965 return;
966 }
967
968 // The DelayLastRR field is in units of 1/65536 sec.
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000969 uint32_t delay_rr_ms =
970 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0x0000ffff) * 1000) >> 16) +
971 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0xffff0000) >> 16) * 1000);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000972
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000973 int32_t rtt = _clock->CurrentNtpInMilliseconds() - delay_rr_ms - send_time_ms;
974
975 xr_rr_rtt_ms_ = static_cast<uint16_t>(std::max(rtt, 1));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000976
977 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
978}
979
niklase@google.com470e71d2011-07-07 08:21:25 +0000980// no need for critsect we have _criticalSectionRTCPReceiver
981void
982RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
983 RTCPPacketInformation& rtcpPacketInformation)
984{
985 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
986
987 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
988
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000989 if(rtcpPacket.XRVOIPMetricItem.SSRC == main_ssrc_)
niklase@google.com470e71d2011-07-07 08:21:25 +0000990 {
991 // Store VoIP metrics block if it's about me
992 // from OriginatorSSRC do we filter it?
993 // rtcpPacket.XR.OriginatorSSRC;
994
995 RTCPVoIPMetric receivedVoIPMetrics;
996 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
997 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
998 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
999 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
1000 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
1001 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
1002 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
1003 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
1004 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
1005 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
1006 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
1007 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
1008 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
1009 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
1010 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
1011 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
1012 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
1013 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
1014 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
1015 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
1016
1017 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
1018
1019 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
1020 }
1021 rtcpParser.Iterate();
1022}
1023
1024// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001025void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
1026 RTCPPacketInformation& rtcpPacketInformation) {
1027 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001028 if (main_ssrc_ == rtcpPacket.PLI.MediaSSRC) {
justinlin@chromium.org7bfb3a32013-05-13 22:59:00 +00001029 TRACE_EVENT_INSTANT0("webrtc_rtp", "PLI");
1030
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001031 ++packet_type_counter_.pli_packets;
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001032 // Received a signal that we need to send a new key frame.
1033 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
1034 }
1035 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001036}
1037
1038// no need for critsect we have _criticalSectionRTCPReceiver
1039void
1040RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
1041 RTCPPacketInformation& rtcpPacketInformation)
1042{
1043 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1044
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001045 uint32_t senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001046 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
1047 if (ptrReceiveInfo == NULL)
1048 {
1049 // This remote SSRC must be saved before.
1050 rtcpParser.Iterate();
1051 return;
1052 }
1053 if(rtcpPacket.TMMBR.MediaSSRC)
1054 {
1055 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
1056 // in relay mode this is a valid number
1057 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
1058 }
1059
1060 // Use packet length to calc max number of TMMBR blocks
1061 // each TMMBR block is 8 bytes
1062 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
1063
1064 // sanity
1065 if(maxNumOfTMMBRBlocks > 200) // we can't have more than what's in one packet
1066 {
1067 assert(false);
1068 rtcpParser.Iterate();
1069 return;
1070 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001071 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((uint32_t)maxNumOfTMMBRBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001072
1073 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1074 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode)
1075 {
1076 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
1077 pktType = rtcpParser.Iterate();
1078 }
1079}
1080
1081// no need for critsect we have _criticalSectionRTCPReceiver
1082void
1083RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
1084 const RTCPUtility::RTCPPacket& rtcpPacket,
1085 RTCPPacketInformation& rtcpPacketInformation,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001086 const uint32_t senderSSRC)
niklase@google.com470e71d2011-07-07 08:21:25 +00001087{
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001088 if (main_ssrc_ == rtcpPacket.TMMBRItem.SSRC &&
niklase@google.com470e71d2011-07-07 08:21:25 +00001089 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
1090 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001091 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001092 _clock->TimeInMilliseconds());
niklase@google.com470e71d2011-07-07 08:21:25 +00001093 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
1094 }
1095}
1096
1097// no need for critsect we have _criticalSectionRTCPReceiver
1098void
hta@webrtc.org9d54cd12012-04-30 08:24:55 +00001099RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
1100 RTCPPacketInformation& rtcpPacketInformation)
niklase@google.com470e71d2011-07-07 08:21:25 +00001101{
1102 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1103 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.TMMBN.SenderSSRC);
1104 if (ptrReceiveInfo == NULL)
1105 {
1106 // This remote SSRC must be saved before.
1107 rtcpParser.Iterate();
1108 return;
1109 }
hta@webrtc.org9d54cd12012-04-30 08:24:55 +00001110 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +00001111 // Use packet length to calc max number of TMMBN blocks
1112 // each TMMBN block is 8 bytes
1113 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
1114
1115 // sanity
1116 if(maxNumOfTMMBNBlocks > 200) // we cant have more than what's in one packet
1117 {
1118 assert(false);
1119 rtcpParser.Iterate();
1120 return;
1121 }
1122
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001123 ptrReceiveInfo->VerifyAndAllocateBoundingSet((uint32_t)maxNumOfTMMBNBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001124
1125 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1126 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode)
1127 {
1128 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
1129 pktType = rtcpParser.Iterate();
1130 }
1131}
1132
1133// no need for critsect we have _criticalSectionRTCPReceiver
1134void
1135RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
1136 RTCPPacketInformation& rtcpPacketInformation)
1137{
1138 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
1139 rtcpParser.Iterate();
1140}
1141
1142// no need for critsect we have _criticalSectionRTCPReceiver
1143void
1144RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
1145 const RTCPUtility::RTCPPacket& rtcpPacket)
1146{
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001147 receiveInfo.TmmbnBoundingSet.AddEntry(
1148 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
1149 rtcpPacket.TMMBNItem.MeasuredOverhead,
1150 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001151}
1152
1153// no need for critsect we have _criticalSectionRTCPReceiver
1154void
1155RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
1156 RTCPPacketInformation& rtcpPacketInformation)
1157{
1158 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001159 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1160 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode)
1161 {
1162 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1163 pktType = rtcpParser.Iterate();
1164 }
1165}
1166
1167// no need for critsect we have _criticalSectionRTCPReceiver
1168void
1169RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1170 RTCPPacketInformation& rtcpPacketInformation)
1171{
1172 // in theory there could be multiple slices lost
1173 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1174 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
1175}
1176
1177void
1178RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1179 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1180{
1181 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001182 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1183 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1184 {
1185 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1186 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1187 {
1188 // to us unknown
1189 // continue
1190 rtcpParser.Iterate();
1191 return;
1192 }
1193 rtcpPacketInformation.rpsiPictureId = 0;
1194
1195 // convert NativeBitString to rpsiPictureId
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001196 uint8_t numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1197 for(uint8_t n = 0; n < (numberOfBytes-1); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001198 {
1199 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1200 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1201 }
1202 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1203 }
1204}
1205
1206// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001207void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1208 RTCPPacketInformation& rtcpPacketInformation) {
1209 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1210 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1211 pktType = rtcpParser.Iterate();
1212 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1213 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1214 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001215 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001216 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001217}
1218
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001219// no need for critsect we have _criticalSectionRTCPReceiver
1220void
1221RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1222 RTCPPacketInformation& rtcpPacketInformation)
1223{
1224 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1225
1226 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1227 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode)
1228 {
1229 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1230 pktType = rtcpParser.Iterate();
1231 }
1232}
1233
1234void
1235RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1236 RTCPPacketInformation& rtcpPacketInformation)
1237{
1238 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1239 rtcpPacketInformation.interArrivalJitter =
1240 rtcpPacket.ExtendedJitterReportItem.Jitter;
1241}
1242
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001243void RTCPReceiver::HandleREMBItem(
1244 RTCPUtility::RTCPParserV2& rtcpParser,
1245 RTCPPacketInformation& rtcpPacketInformation) {
1246 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1247 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1248 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1249 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001250}
1251
1252// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001253void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1254 RTCPPacketInformation& rtcpPacketInformation) {
1255 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1256 RTCPReceiveInformation* ptrReceiveInfo =
1257 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001258
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001259 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1260 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1261 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1262 pktType = rtcpParser.Iterate();
1263 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001264}
1265
1266// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001267void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1268 const RTCPUtility::RTCPPacket& rtcpPacket,
1269 RTCPPacketInformation& rtcpPacketInformation) {
1270 // Is it our sender that is requested to generate a new keyframe
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001271 if (main_ssrc_ != rtcpPacket.FIRItem.SSRC) {
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001272 return;
1273 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001274
1275 ++packet_type_counter_.fir_packets;
1276
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001277 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1278 // we don't know who this originate from
1279 if (receiveInfo) {
1280 // check if we have reported this FIRSequenceNumber before
1281 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1282 receiveInfo->lastFIRSequenceNumber) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001283 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001284 // sanity; don't go crazy with the callbacks
1285 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1286 receiveInfo->lastFIRRequest = now;
1287 receiveInfo->lastFIRSequenceNumber =
1288 rtcpPacket.FIRItem.CommandSequenceNumber;
1289 // received signal that we need to send a new key frame
1290 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1291 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001292 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001293 } else {
1294 // received signal that we need to send a new key frame
1295 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1296 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001297}
1298
1299void
1300RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1301 RTCPPacketInformation& rtcpPacketInformation)
1302{
1303 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1304
1305 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1306 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1307 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
1308
1309 rtcpParser.Iterate();
1310}
1311
1312void
1313RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1314 RTCPPacketInformation& rtcpPacketInformation)
1315{
1316 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1317
1318 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
1319
1320 rtcpParser.Iterate();
1321}
1322
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001323int32_t RTCPReceiver::UpdateTMMBR() {
1324 int32_t numBoundingSet = 0;
1325 uint32_t bitrate = 0;
1326 uint32_t accNumCandidates = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001327
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001328 int32_t size = TMMBRReceived(0, 0, NULL);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001329 if (size > 0) {
1330 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1331 // Get candidate set from receiver.
1332 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1333 } else {
1334 // Candidate set empty.
1335 VerifyAndAllocateCandidateSet(0); // resets candidate set
1336 }
1337 // Find bounding set
1338 TMMBRSet* boundingSet = NULL;
1339 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1340 if (numBoundingSet == -1) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001341 LOG(LS_WARNING) << "Failed to find TMMBR bounding set.";
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001342 return -1;
1343 }
1344 // Set bounding set
1345 // Inform remote clients about the new bandwidth
1346 // inform the remote client
1347 _rtpRtcp.SetTMMBN(boundingSet);
1348
1349 // might trigger a TMMBN
1350 if (numBoundingSet == 0) {
1351 // owner of max bitrate request has timed out
1352 // empty bounding set has been sent
1353 return 0;
1354 }
1355 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001356 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001357 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001358 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1359 if (_cbRtcpBandwidthObserver) {
1360 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001361 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001362 }
1363 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001364}
1365
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001366void RTCPReceiver::RegisterRtcpStatisticsCallback(
1367 RtcpStatisticsCallback* callback) {
1368 CriticalSectionScoped cs(_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001369 stats_callback_ = callback;
1370}
1371
1372RtcpStatisticsCallback* RTCPReceiver::GetRtcpStatisticsCallback() {
1373 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1374 return stats_callback_;
1375}
1376
niklase@google.com470e71d2011-07-07 08:21:25 +00001377// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001378void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001379 RTCPPacketInformation& rtcpPacketInformation) {
1380 // Process TMMBR and REMB first to avoid multiple callbacks
1381 // to OnNetworkChanged.
1382 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001383 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1384 UpdateTMMBR();
1385 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001386 unsigned int local_ssrc = 0;
1387 {
1388 // We don't want to hold this critsect when triggering the callbacks below.
1389 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001390 local_ssrc = main_ssrc_;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001391 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001392 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1393 _rtpRtcp.OnRequestSendReport();
1394 }
1395 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001396 if (rtcpPacketInformation.nackSequenceNumbers.size() > 0) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001397 LOG(LS_VERBOSE) << "Incoming NACK length: "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001398 << rtcpPacketInformation.nackSequenceNumbers.size();
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001399 _rtpRtcp.OnReceivedNACK(rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001400 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001401 }
1402 {
1403 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001404
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001405 // We need feedback that we have received a report block(s) so that we
1406 // can generate a new packet in a conference relay scenario, one received
1407 // report can generate several RTCP packets, based on number relayed/mixed
1408 // a send report block should go out to all receivers.
1409 if (_cbRtcpIntraFrameObserver) {
1410 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1411 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1412 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001413 LOG(LS_VERBOSE) << "Incoming PLI from SSRC "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001414 << rtcpPacketInformation.remoteSSRC;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001415 } else {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001416 LOG(LS_VERBOSE) << "Incoming FIR from SSRC "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001417 << rtcpPacketInformation.remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001418 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001419 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001420 }
1421 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1422 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001423 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001424 }
1425 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1426 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001427 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001428 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001429 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001430 if (_cbRtcpBandwidthObserver) {
1431 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001432 LOG(LS_VERBOSE) << "Incoming REMB: "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001433 << rtcpPacketInformation.receiverEstimatedMaxBitrate;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001434 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1435 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1436 }
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001437 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1438 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001439 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001440 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001441 rtcpPacketInformation.report_blocks,
1442 rtcpPacketInformation.rtt,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001443 now);
1444 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001445 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001446 }
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001447
1448 {
1449 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1450 if (stats_callback_) {
1451 for (ReportBlockList::const_iterator it =
1452 rtcpPacketInformation.report_blocks.begin();
1453 it != rtcpPacketInformation.report_blocks.end();
1454 ++it) {
1455 RtcpStatistics stats;
1456 stats.cumulative_lost = it->cumulativeLost;
1457 stats.extended_max_sequence_number = it->extendedHighSeqNum;
1458 stats.fraction_lost = it->fractionLost;
1459 stats.jitter = it->jitter;
1460
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001461 stats_callback_->StatisticsUpdated(stats, it->sourceSSRC);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001462 }
1463 }
1464 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001465}
1466
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001467int32_t RTCPReceiver::CNAME(const uint32_t remoteSSRC,
1468 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001469 assert(cName);
1470
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001471 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1472 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001473 if (cnameInfo == NULL) {
1474 return -1;
1475 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001476 cName[RTCP_CNAME_SIZE - 1] = 0;
1477 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1478 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001479}
1480
1481// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001482int32_t RTCPReceiver::TMMBRReceived(const uint32_t size,
1483 const uint32_t accNumCandidates,
1484 TMMBRSet* candidateSet) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001485 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001486
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001487 std::map<uint32_t, RTCPReceiveInformation*>::const_iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001488 receiveInfoIt = _receivedInfoMap.begin();
1489 if (receiveInfoIt == _receivedInfoMap.end()) {
1490 return -1;
1491 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001492 uint32_t num = accNumCandidates;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001493 if (candidateSet) {
1494 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1495 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1496 if (receiveInfo == NULL) {
1497 return 0;
1498 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001499 for (uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001500 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001501 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001502 _clock->TimeInMilliseconds()) == 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001503 num++;
1504 }
1505 }
1506 receiveInfoIt++;
1507 }
1508 } else {
1509 while (receiveInfoIt != _receivedInfoMap.end()) {
1510 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1511 if(receiveInfo == NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001512 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001513 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001514 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001515 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001516 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001517 }
1518 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001519}
1520
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001521} // namespace webrtc