blob: 02f1fa350a3bcaac2c69b27220c27a47a9aecc24 [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.org1d0fa5d2015-02-19 12:47:00 +000031RTCPReceiver::RTCPReceiver(
32 int32_t id,
33 Clock* clock,
34 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
mflodman@webrtc.org96abda02015-02-25 13:50:10 +000035 RtcpBandwidthObserver* rtcp_bandwidth_observer,
36 RtcpIntraFrameObserver* rtcp_intra_frame_observer,
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000037 ModuleRtpRtcpImpl* owner)
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000038 : TMMBRHelp(),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000039 _clock(clock),
40 _method(kRtcpOff),
41 _lastReceived(0),
42 _rtpRtcp(*owner),
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000043 _criticalSectionFeedbacks(
44 CriticalSectionWrapper::CreateCriticalSection()),
mflodman@webrtc.org96abda02015-02-25 13:50:10 +000045 _cbRtcpBandwidthObserver(rtcp_bandwidth_observer),
46 _cbRtcpIntraFrameObserver(rtcp_intra_frame_observer),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000047 _criticalSectionRTCPReceiver(
48 CriticalSectionWrapper::CreateCriticalSection()),
49 main_ssrc_(0),
50 _remoteSSRC(0),
51 _remoteSenderInfo(),
52 _lastReceivedSRNTPsecs(0),
53 _lastReceivedSRNTPfrac(0),
54 _lastReceivedXRNTPsecs(0),
55 _lastReceivedXRNTPfrac(0),
56 xr_rr_rtt_ms_(0),
57 _receivedInfoMap(),
58 _packetTimeOutMS(0),
59 _lastReceivedRrMs(0),
60 _lastIncreasedSequenceNumberMs(0),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000061 stats_callback_(NULL),
62 packet_type_counter_observer_(packet_type_counter_observer) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +000063 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
niklase@google.com470e71d2011-07-07 08:21:25 +000064}
65
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000066RTCPReceiver::~RTCPReceiver() {
67 delete _criticalSectionRTCPReceiver;
68 delete _criticalSectionFeedbacks;
niklase@google.com470e71d2011-07-07 08:21:25 +000069
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +000070 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
71 for (; it != _receivedReportBlockMap.end(); ++it) {
72 ReportBlockInfoMap* info_map = &(it->second);
73 while (!info_map->empty()) {
74 ReportBlockInfoMap::iterator it_info = info_map->begin();
75 delete it_info->second;
76 info_map->erase(it_info);
77 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000078 }
79 while (!_receivedInfoMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000080 std::map<uint32_t, RTCPReceiveInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000081 _receivedInfoMap.begin();
82 delete first->second;
83 _receivedInfoMap.erase(first);
84 }
85 while (!_receivedCnameMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000086 std::map<uint32_t, RTCPCnameInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000087 _receivedCnameMap.begin();
88 delete first->second;
89 _receivedCnameMap.erase(first);
90 }
niklase@google.com470e71d2011-07-07 08:21:25 +000091}
92
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +000093RTCPMethod RTCPReceiver::Status() const {
94 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
95 return _method;
niklase@google.com470e71d2011-07-07 08:21:25 +000096}
97
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000098void RTCPReceiver::SetRTCPStatus(RTCPMethod method) {
99 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
100 _method = method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000101}
102
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000103int64_t RTCPReceiver::LastReceived() {
104 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
105 return _lastReceived;
niklase@google.com470e71d2011-07-07 08:21:25 +0000106}
107
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000108int64_t RTCPReceiver::LastReceivedReceiverReport() const {
109 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
110 int64_t last_received_rr = -1;
111 for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin();
112 it != _receivedInfoMap.end(); ++it) {
113 if (it->second->lastTimeReceived > last_received_rr) {
114 last_received_rr = it->second->lastTimeReceived;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000115 }
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000116 }
117 return last_received_rr;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000118}
119
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000120void RTCPReceiver::SetRemoteSSRC(uint32_t ssrc) {
121 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000122
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000123 // new SSRC reset old reports
124 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
125 _lastReceivedSRNTPsecs = 0;
126 _lastReceivedSRNTPfrac = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000127
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000128 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000129}
130
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000131uint32_t RTCPReceiver::RemoteSSRC() const {
132 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
133 return _remoteSSRC;
134}
135
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000136void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
137 const std::set<uint32_t>& registered_ssrcs) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000138 uint32_t old_ssrc = 0;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000139 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000140 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000141 old_ssrc = main_ssrc_;
142 main_ssrc_ = main_ssrc;
143 registered_ssrcs_ = registered_ssrcs;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000144 }
145 {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000146 if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) {
147 _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc);
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000148 }
149 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000150}
151
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000152int32_t RTCPReceiver::RTT(uint32_t remoteSSRC,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000153 int64_t* RTT,
154 int64_t* avgRTT,
155 int64_t* minRTT,
156 int64_t* maxRTT) const {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000157 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000158
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000159 RTCPReportBlockInformation* reportBlock =
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000160 GetReportBlockInformation(remoteSSRC, main_ssrc_);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000161
162 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000163 return -1;
164 }
165 if (RTT) {
166 *RTT = reportBlock->RTT;
167 }
168 if (avgRTT) {
169 *avgRTT = reportBlock->avgRTT;
170 }
171 if (minRTT) {
172 *minRTT = reportBlock->minRTT;
173 }
174 if (maxRTT) {
175 *maxRTT = reportBlock->maxRTT;
176 }
177 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000178}
179
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000180bool RTCPReceiver::GetAndResetXrRrRtt(int64_t* rtt_ms) {
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000181 assert(rtt_ms);
182 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
183 if (xr_rr_rtt_ms_ == 0) {
184 return false;
185 }
186 *rtt_ms = xr_rr_rtt_ms_;
187 xr_rr_rtt_ms_ = 0;
188 return true;
189}
190
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000191// TODO(pbos): Make this fail when we haven't received NTP.
192bool RTCPReceiver::NTP(uint32_t* ReceivedNTPsecs,
193 uint32_t* ReceivedNTPfrac,
194 uint32_t* RTCPArrivalTimeSecs,
195 uint32_t* RTCPArrivalTimeFrac,
196 uint32_t* rtcp_timestamp) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000197{
198 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
199 if(ReceivedNTPsecs)
200 {
201 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
202 }
203 if(ReceivedNTPfrac)
204 {
205 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
206 }
207 if(RTCPArrivalTimeFrac)
208 {
209 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
210 }
211 if(RTCPArrivalTimeSecs)
212 {
213 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
214 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000215 if (rtcp_timestamp) {
216 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
217 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000218 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000219}
220
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000221bool RTCPReceiver::LastReceivedXrReferenceTimeInfo(
222 RtcpReceiveTimeInfo* info) const {
223 assert(info);
224 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
225 if (_lastReceivedXRNTPsecs == 0 && _lastReceivedXRNTPfrac == 0) {
226 return false;
227 }
228
229 info->sourceSSRC = _remoteXRReceiveTimeInfo.sourceSSRC;
230 info->lastRR = _remoteXRReceiveTimeInfo.lastRR;
231
232 // Get the delay since last received report (RFC 3611).
233 uint32_t receive_time = RTCPUtility::MidNtp(_lastReceivedXRNTPsecs,
234 _lastReceivedXRNTPfrac);
235
236 uint32_t ntp_sec = 0;
237 uint32_t ntp_frac = 0;
238 _clock->CurrentNtp(ntp_sec, ntp_frac);
239 uint32_t now = RTCPUtility::MidNtp(ntp_sec, ntp_frac);
240
241 info->delaySinceLastRR = now - receive_time;
242 return true;
243}
244
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000245int32_t RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const {
246 assert(senderInfo);
247 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
248 if (_lastReceivedSRNTPsecs == 0) {
249 return -1;
250 }
251 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
252 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000253}
254
255// statistics
256// we can get multiple receive reports when we receive the report from a CE
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000257int32_t RTCPReceiver::StatisticsReceived(
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000258 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000259 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000260 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000261 ReportBlockMap::const_iterator it = _receivedReportBlockMap.begin();
262 for (; it != _receivedReportBlockMap.end(); ++it) {
263 const ReportBlockInfoMap* info_map = &(it->second);
264 ReportBlockInfoMap::const_iterator it_info = info_map->begin();
265 for (; it_info != info_map->end(); ++it_info) {
266 receiveBlocks->push_back(it_info->second->remoteReceiveBlock);
267 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000268 }
269 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000270}
271
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000272int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000273RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
274 RTCPUtility::RTCPParserV2* rtcpParser)
275{
276 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
277
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000278 _lastReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000279
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000280 if (packet_type_counter_.first_packet_time_ms == -1) {
281 packet_type_counter_.first_packet_time_ms = _lastReceived;
282 }
283
niklase@google.com470e71d2011-07-07 08:21:25 +0000284 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
285 while (pktType != RTCPUtility::kRtcpNotValidCode)
286 {
287 // Each "case" is responsible for iterate the parser to the
288 // next top level packet.
289 switch (pktType)
290 {
291 case RTCPUtility::kRtcpSrCode:
292 case RTCPUtility::kRtcpRrCode:
293 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
294 break;
295 case RTCPUtility::kRtcpSdesCode:
296 HandleSDES(*rtcpParser);
297 break;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000298 case RTCPUtility::kRtcpXrHeaderCode:
299 HandleXrHeader(*rtcpParser, rtcpPacketInformation);
300 break;
301 case RTCPUtility::kRtcpXrReceiverReferenceTimeCode:
302 HandleXrReceiveReferenceTime(*rtcpParser, rtcpPacketInformation);
303 break;
304 case RTCPUtility::kRtcpXrDlrrReportBlockCode:
305 HandleXrDlrrReportBlock(*rtcpParser, rtcpPacketInformation);
306 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000307 case RTCPUtility::kRtcpXrVoipMetricCode:
308 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
309 break;
310 case RTCPUtility::kRtcpByeCode:
311 HandleBYE(*rtcpParser);
312 break;
313 case RTCPUtility::kRtcpRtpfbNackCode:
314 HandleNACK(*rtcpParser, rtcpPacketInformation);
315 break;
316 case RTCPUtility::kRtcpRtpfbTmmbrCode:
317 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
318 break;
319 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000320 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000321 break;
322 case RTCPUtility::kRtcpRtpfbSrReqCode:
323 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
324 break;
325 case RTCPUtility::kRtcpPsfbPliCode:
326 HandlePLI(*rtcpParser, rtcpPacketInformation);
327 break;
328 case RTCPUtility::kRtcpPsfbSliCode:
329 HandleSLI(*rtcpParser, rtcpPacketInformation);
330 break;
331 case RTCPUtility::kRtcpPsfbRpsiCode:
332 HandleRPSI(*rtcpParser, rtcpPacketInformation);
333 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000334 case RTCPUtility::kRtcpExtendedIjCode:
335 HandleIJ(*rtcpParser, rtcpPacketInformation);
336 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000337 case RTCPUtility::kRtcpPsfbFirCode:
338 HandleFIR(*rtcpParser, rtcpPacketInformation);
339 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000340 case RTCPUtility::kRtcpPsfbAppCode:
341 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
342 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000343 case RTCPUtility::kRtcpAppCode:
344 // generic application messages
345 HandleAPP(*rtcpParser, rtcpPacketInformation);
346 break;
347 case RTCPUtility::kRtcpAppItemCode:
348 // generic application messages
349 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
350 break;
351 default:
352 rtcpParser->Iterate();
353 break;
354 }
355 pktType = rtcpParser->PacketType();
356 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000357
358 if (packet_type_counter_observer_ != NULL) {
359 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
360 main_ssrc_, packet_type_counter_);
361 }
362
niklase@google.com470e71d2011-07-07 08:21:25 +0000363 return 0;
364}
365
366// no need for critsect we have _criticalSectionRTCPReceiver
367void
368RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
369 RTCPPacketInformation& rtcpPacketInformation)
370{
371 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
372 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
373
374 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
375
376 // SR.SenderSSRC
377 // The synchronization source identifier for the originator of this SR packet
378
379 // rtcpPacket.RR.SenderSSRC
380 // The source of the packet sender, same as of SR? or is this a CE?
381
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000382 const uint32_t remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +0000383
384 rtcpPacketInformation.remoteSSRC = remoteSSRC;
385
386 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
387 if (!ptrReceiveInfo)
388 {
389 rtcpParser.Iterate();
390 return;
391 }
392
393 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
394 {
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000395 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "SR",
396 "remote_ssrc", remoteSSRC, "ssrc", main_ssrc_);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000397
niklase@google.com470e71d2011-07-07 08:21:25 +0000398 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
399 {
400 // only signal that we have received a SR when we accept one
401 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
402
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000403 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
404 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
405 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
406
niklase@google.com470e71d2011-07-07 08:21:25 +0000407 // We will only store the send report from one source, but
408 // we will store all the receive block
409
410 // Save the NTP time of this report
411 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
412 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
413 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
414 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
415 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
416
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000417 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000418 }
419 else
420 {
421 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
422 }
423 } else
424 {
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000425 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RR",
426 "remote_ssrc", remoteSSRC, "ssrc", main_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000427
428 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
429 }
430 UpdateReceiveInformation(*ptrReceiveInfo);
431
432 rtcpPacketType = rtcpParser.Iterate();
433
434 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
435 {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000436 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000437 rtcpPacketType = rtcpParser.Iterate();
438 }
439}
440
441// no need for critsect we have _criticalSectionRTCPReceiver
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000442void RTCPReceiver::HandleReportBlock(
443 const RTCPUtility::RTCPPacket& rtcpPacket,
444 RTCPPacketInformation& rtcpPacketInformation,
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000445 uint32_t remoteSSRC)
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000446 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000447 // This will be called once per report block in the RTCP packet.
448 // We filter out all report blocks that are not for us.
449 // Each packet has max 31 RR blocks.
450 //
451 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000452
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000453 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
454 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000455
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000456 // Filter out all report blocks that are not for us.
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000457 if (registered_ssrcs_.find(rtcpPacket.ReportBlockItem.SSRC) ==
458 registered_ssrcs_.end()) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000459 // This block is not for us ignore it.
460 return;
461 }
462
463 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
464 // _criticalSectionRTCPReceiver.
465 _criticalSectionRTCPReceiver->Leave();
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000466 int64_t sendTimeMS =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000467 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
468 _criticalSectionRTCPReceiver->Enter();
469
470 RTCPReportBlockInformation* reportBlock =
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000471 CreateOrGetReportBlockInformation(remoteSSRC,
472 rtcpPacket.ReportBlockItem.SSRC);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000473 if (reportBlock == NULL) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000474 LOG(LS_WARNING) << "Failed to CreateReportBlockInformation("
475 << remoteSSRC << ")";
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000476 return;
477 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000478
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000479 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000480 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
481 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
482 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
483 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
484 reportBlock->remoteReceiveBlock.cumulativeLost =
485 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000486 if (rb.ExtendedHighestSequenceNumber >
487 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
488 // We have successfully delivered new RTP packets to the remote side after
489 // the last RR was sent from the remote side.
490 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000491 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000492 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
493 rb.ExtendedHighestSequenceNumber;
494 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
495 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
496 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
497
498 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
499 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
500 }
501
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000502 uint32_t delaySinceLastSendReport =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000503 rtcpPacket.ReportBlockItem.DelayLastSR;
504
505 // local NTP time when we received this
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000506 uint32_t lastReceivedRRNTPsecs = 0;
507 uint32_t lastReceivedRRNTPfrac = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000508
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000509 _clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000510
511 // time when we received this in MS
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000512 int64_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
513 lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000514
515 // Estimate RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000516 uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000517 d /= 65536;
518 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
519
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000520 int64_t RTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000521
522 if (sendTimeMS > 0) {
523 RTT = receiveTimeMS - d - sendTimeMS;
524 if (RTT <= 0) {
525 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000526 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000527 if (RTT > reportBlock->maxRTT) {
528 // store max RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000529 reportBlock->maxRTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000530 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000531 if (reportBlock->minRTT == 0) {
532 // first RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000533 reportBlock->minRTT = RTT;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000534 } else if (RTT < reportBlock->minRTT) {
535 // Store min RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000536 reportBlock->minRTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000537 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000538 // store last RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000539 reportBlock->RTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000540
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000541 // store average RTT
542 if (reportBlock->numAverageCalcs != 0) {
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000543 float ac = static_cast<float>(reportBlock->numAverageCalcs);
544 float newAverage =
545 ((ac / (ac + 1)) * reportBlock->avgRTT) + ((1 / (ac + 1)) * RTT);
546 reportBlock->avgRTT = static_cast<int64_t>(newAverage + 0.5f);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000547 } else {
548 // first RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000549 reportBlock->avgRTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000550 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000551 reportBlock->numAverageCalcs++;
552 }
553
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000554 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RR_RTT", rb.SSRC,
555 RTT);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000556
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000557 rtcpPacketInformation.AddReportInfo(*reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000558}
559
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000560RTCPReportBlockInformation* RTCPReceiver::CreateOrGetReportBlockInformation(
561 uint32_t remote_ssrc,
562 uint32_t source_ssrc) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000563 RTCPReportBlockInformation* info =
564 GetReportBlockInformation(remote_ssrc, source_ssrc);
565 if (info == NULL) {
566 info = new RTCPReportBlockInformation;
567 _receivedReportBlockMap[source_ssrc][remote_ssrc] = info;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000568 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000569 return info;
niklase@google.com470e71d2011-07-07 08:21:25 +0000570}
571
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000572RTCPReportBlockInformation* RTCPReceiver::GetReportBlockInformation(
573 uint32_t remote_ssrc,
574 uint32_t source_ssrc) const {
575 ReportBlockMap::const_iterator it = _receivedReportBlockMap.find(source_ssrc);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000576 if (it == _receivedReportBlockMap.end()) {
577 return NULL;
578 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000579 const ReportBlockInfoMap* info_map = &(it->second);
580 ReportBlockInfoMap::const_iterator it_info = info_map->find(remote_ssrc);
581 if (it_info == info_map->end()) {
582 return NULL;
583 }
584 return it_info->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000585}
586
587RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000588RTCPReceiver::CreateCnameInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000589 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000590
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000591 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000592 _receivedCnameMap.find(remoteSSRC);
593
594 if (it != _receivedCnameMap.end()) {
595 return it->second;
596 }
597 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000598 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000599 _receivedCnameMap[remoteSSRC] = cnameInfo;
600 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000601}
602
603RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000604RTCPReceiver::GetCnameInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000605 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000606
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000607 std::map<uint32_t, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000608 _receivedCnameMap.find(remoteSSRC);
609
610 if (it == _receivedCnameMap.end()) {
611 return NULL;
612 }
613 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000614}
615
616RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000617RTCPReceiver::CreateReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000618 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000619
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000620 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000621 _receivedInfoMap.find(remoteSSRC);
622
623 if (it != _receivedInfoMap.end()) {
624 return it->second;
625 }
626 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
627 _receivedInfoMap[remoteSSRC] = receiveInfo;
628 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000629}
630
631RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000632RTCPReceiver::GetReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000633 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000634
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000635 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000636 _receivedInfoMap.find(remoteSSRC);
637 if (it == _receivedInfoMap.end()) {
638 return NULL;
639 }
640 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000641}
642
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000643void RTCPReceiver::UpdateReceiveInformation(
644 RTCPReceiveInformation& receiveInformation) {
645 // Update that this remote is alive
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000646 receiveInformation.lastTimeReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000647}
648
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000649bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
650 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
651 if (_lastReceivedRrMs == 0)
652 return false;
653
654 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000655 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000656 // Reset the timer to only trigger one log.
657 _lastReceivedRrMs = 0;
658 return true;
659 }
660 return false;
661}
662
663bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
664 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
665 if (_lastIncreasedSequenceNumberMs == 0)
666 return false;
667
668 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000669 if (_clock->TimeInMilliseconds() > _lastIncreasedSequenceNumberMs +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000670 time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000671 // Reset the timer to only trigger one log.
672 _lastIncreasedSequenceNumberMs = 0;
673 return true;
674 }
675 return false;
676}
677
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000678bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
679 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000680
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000681 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000682 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000683
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000684 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000685 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000686
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000687 while (receiveInfoIt != _receivedInfoMap.end()) {
688 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
689 if (receiveInfo == NULL) {
690 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000691 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000692 // time since last received rtcp packet
693 // when we dont have a lastTimeReceived and the object is marked
694 // readyForDelete it's removed from the map
695 if (receiveInfo->lastTimeReceived) {
696 /// use audio define since we don't know what interval the remote peer is
697 // using
698 if ((timeNow - receiveInfo->lastTimeReceived) >
699 5 * RTCP_INTERVAL_AUDIO_MS) {
700 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000701 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000702 // prevent that we call this over and over again
703 receiveInfo->lastTimeReceived = 0;
704 // send new TMMBN to all channels using the default codec
705 updateBoundingSet = true;
706 }
707 receiveInfoIt++;
708 } else if (receiveInfo->readyForDelete) {
709 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000710 std::map<uint32_t, RTCPReceiveInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000711 receiveInfoItemToBeErased = receiveInfoIt;
712 receiveInfoIt++;
713 delete receiveInfoItemToBeErased->second;
714 _receivedInfoMap.erase(receiveInfoItemToBeErased);
715 } else {
716 receiveInfoIt++;
717 }
718 }
719 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000720}
721
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000722int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000723 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000724
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000725 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000726 _receivedInfoMap.find(_remoteSSRC);
727
728 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000729 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000730 }
731 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
732 if (receiveInfo == NULL) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000733 return -1;
734 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000735 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000736 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000737 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000738 for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000739 i++) {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000740 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000741 // owner of bounding set
742 tmmbrOwner = true;
743 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000744 boundingSetRec->SetEntry(i,
745 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
746 receiveInfo->TmmbnBoundingSet.PacketOH(i),
747 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000748 }
749 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000750 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000751}
752
753// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000754void RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser) {
755 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
756 while (pktType == RTCPUtility::kRtcpSdesChunkCode) {
757 HandleSDESChunk(rtcpParser);
758 pktType = rtcpParser.Iterate();
759 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000760}
761
762// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000763void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
764 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
765 RTCPCnameInformation* cnameInfo =
766 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
767 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000768
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000769 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
770 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000771 {
772 CriticalSectionScoped lock(_criticalSectionFeedbacks);
773 if (stats_callback_ != NULL) {
774 stats_callback_->CNameChanged(rtcpPacket.CName.CName,
775 rtcpPacket.CName.SenderSSRC);
776 }
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000777 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000778}
779
780// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000781void RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
782 RTCPPacketInformation& rtcpPacketInformation) {
783 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
784 if (main_ssrc_ != rtcpPacket.NACK.MediaSSRC) {
785 // Not to us.
786 rtcpParser.Iterate();
787 return;
788 }
789 rtcpPacketInformation.ResetNACKPacketIdArray();
niklase@google.com470e71d2011-07-07 08:21:25 +0000790
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000791 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
792 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode) {
793 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
794 pktType = rtcpParser.Iterate();
795 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000796
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000797 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
798 ++packet_type_counter_.nack_packets;
799 packet_type_counter_.nack_requests = nack_stats_.requests();
800 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
801 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000802}
803
804// no need for critsect we have _criticalSectionRTCPReceiver
805void
806RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000807 RTCPPacketInformation& rtcpPacketInformation) {
808 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
809 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000810
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000811 uint16_t bitMask = rtcpPacket.NACKItem.BitMask;
812 if (bitMask) {
813 for (int i=1; i <= 16; ++i) {
814 if (bitMask & 0x01) {
815 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
816 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID + i);
817 }
818 bitMask = bitMask >>1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000819 }
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000820 }
821 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
niklase@google.com470e71d2011-07-07 08:21:25 +0000822}
823
824// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000825void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
826 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000827
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000828 // clear our lists
829 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000830 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
831 for (; it != _receivedReportBlockMap.end(); ++it) {
832 ReportBlockInfoMap* info_map = &(it->second);
833 ReportBlockInfoMap::iterator it_info = info_map->find(
834 rtcpPacket.BYE.SenderSSRC);
835 if (it_info != info_map->end()) {
836 delete it_info->second;
837 info_map->erase(it_info);
838 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000839 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000840
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000841 // we can't delete it due to TMMBR
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000842 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000843 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000844
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000845 if (receiveInfoIt != _receivedInfoMap.end()) {
846 receiveInfoIt->second->readyForDelete = true;
847 }
848
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000849 std::map<uint32_t, RTCPCnameInformation*>::iterator cnameInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000850 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
851
852 if (cnameInfoIt != _receivedCnameMap.end()) {
853 delete cnameInfoIt->second;
854 _receivedCnameMap.erase(cnameInfoIt);
855 }
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000856 xr_rr_rtt_ms_ = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000857 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000858}
859
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000860void RTCPReceiver::HandleXrHeader(
861 RTCPUtility::RTCPParserV2& parser,
862 RTCPPacketInformation& rtcpPacketInformation) {
863 const RTCPUtility::RTCPPacket& packet = parser.Packet();
864
865 rtcpPacketInformation.xr_originator_ssrc = packet.XR.OriginatorSSRC;
866
867 parser.Iterate();
868}
869
870void RTCPReceiver::HandleXrReceiveReferenceTime(
871 RTCPUtility::RTCPParserV2& parser,
872 RTCPPacketInformation& rtcpPacketInformation) {
873 const RTCPUtility::RTCPPacket& packet = parser.Packet();
874
875 _remoteXRReceiveTimeInfo.sourceSSRC =
876 rtcpPacketInformation.xr_originator_ssrc;
877
878 _remoteXRReceiveTimeInfo.lastRR = RTCPUtility::MidNtp(
879 packet.XRReceiverReferenceTimeItem.NTPMostSignificant,
880 packet.XRReceiverReferenceTimeItem.NTPLeastSignificant);
881
882 _clock->CurrentNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);
883
884 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
885
886 parser.Iterate();
887}
888
889void RTCPReceiver::HandleXrDlrrReportBlock(
890 RTCPUtility::RTCPParserV2& parser,
891 RTCPPacketInformation& rtcpPacketInformation) {
892 const RTCPUtility::RTCPPacket& packet = parser.Packet();
893 // Iterate through sub-block(s), if any.
894 RTCPUtility::RTCPPacketTypes packet_type = parser.Iterate();
895
896 while (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
897 HandleXrDlrrReportBlockItem(packet, rtcpPacketInformation);
898 packet_type = parser.Iterate();
899 }
900}
901
902void RTCPReceiver::HandleXrDlrrReportBlockItem(
903 const RTCPUtility::RTCPPacket& packet,
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000904 RTCPPacketInformation& rtcpPacketInformation)
905 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000906 if (registered_ssrcs_.find(packet.XRDLRRReportBlockItem.SSRC) ==
907 registered_ssrcs_.end()) {
908 // Not to us.
909 return;
910 }
911
912 rtcpPacketInformation.xr_dlrr_item = true;
913
914 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
915 // _criticalSectionRTCPReceiver.
916 _criticalSectionRTCPReceiver->Leave();
917
918 int64_t send_time_ms;
919 bool found = _rtpRtcp.SendTimeOfXrRrReport(
920 packet.XRDLRRReportBlockItem.LastRR, &send_time_ms);
921
922 _criticalSectionRTCPReceiver->Enter();
923
924 if (!found) {
925 return;
926 }
927
928 // The DelayLastRR field is in units of 1/65536 sec.
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000929 uint32_t delay_rr_ms =
930 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0x0000ffff) * 1000) >> 16) +
931 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0xffff0000) >> 16) * 1000);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000932
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000933 int64_t rtt = _clock->CurrentNtpInMilliseconds() - delay_rr_ms - send_time_ms;
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000934
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000935 xr_rr_rtt_ms_ = std::max<int64_t>(rtt, 1);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000936
937 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
938}
939
niklase@google.com470e71d2011-07-07 08:21:25 +0000940// no need for critsect we have _criticalSectionRTCPReceiver
941void
942RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
943 RTCPPacketInformation& rtcpPacketInformation)
944{
945 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
946
947 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
948
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000949 if(rtcpPacket.XRVOIPMetricItem.SSRC == main_ssrc_)
niklase@google.com470e71d2011-07-07 08:21:25 +0000950 {
951 // Store VoIP metrics block if it's about me
952 // from OriginatorSSRC do we filter it?
953 // rtcpPacket.XR.OriginatorSSRC;
954
955 RTCPVoIPMetric receivedVoIPMetrics;
956 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
957 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
958 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
959 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
960 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
961 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
962 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
963 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
964 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
965 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
966 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
967 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
968 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
969 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
970 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
971 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
972 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
973 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
974 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
975 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
976
977 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
978
979 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
980 }
981 rtcpParser.Iterate();
982}
983
984// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000985void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
986 RTCPPacketInformation& rtcpPacketInformation) {
987 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000988 if (main_ssrc_ == rtcpPacket.PLI.MediaSSRC) {
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000989 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "PLI");
justinlin@chromium.org7bfb3a32013-05-13 22:59:00 +0000990
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000991 ++packet_type_counter_.pli_packets;
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000992 // Received a signal that we need to send a new key frame.
993 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
994 }
995 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000996}
997
998// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000999void RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
1000 RTCPPacketInformation& rtcpPacketInformation) {
1001 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001002
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001003 uint32_t senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
1004 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
1005 if (ptrReceiveInfo == NULL) {
1006 // This remote SSRC must be saved before.
1007 rtcpParser.Iterate();
1008 return;
1009 }
1010 if (rtcpPacket.TMMBR.MediaSSRC) {
1011 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
1012 // in relay mode this is a valid number
1013 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
1014 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001015
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001016 // Use packet length to calc max number of TMMBR blocks
1017 // each TMMBR block is 8 bytes
1018 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001019
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001020 // sanity, we can't have more than what's in one packet
1021 if (maxNumOfTMMBRBlocks > 200) {
1022 assert(false);
1023 rtcpParser.Iterate();
1024 return;
1025 }
1026 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((uint32_t)maxNumOfTMMBRBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001027
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001028 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1029 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode) {
1030 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
1031 pktType = rtcpParser.Iterate();
1032 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001033}
1034
1035// no need for critsect we have _criticalSectionRTCPReceiver
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001036void RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
1037 const RTCPUtility::RTCPPacket& rtcpPacket,
1038 RTCPPacketInformation& rtcpPacketInformation,
1039 uint32_t senderSSRC) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001040 if (main_ssrc_ == rtcpPacket.TMMBRItem.SSRC &&
1041 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0) {
1042 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
1043 _clock->TimeInMilliseconds());
1044 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
1045 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001046}
1047
1048// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001049void RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
1050 RTCPPacketInformation& rtcpPacketInformation) {
1051 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1052 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(
1053 rtcpPacket.TMMBN.SenderSSRC);
1054 if (ptrReceiveInfo == NULL) {
1055 // This remote SSRC must be saved before.
niklase@google.com470e71d2011-07-07 08:21:25 +00001056 rtcpParser.Iterate();
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001057 return;
1058 }
1059 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
1060 // Use packet length to calc max number of TMMBN blocks
1061 // each TMMBN block is 8 bytes
1062 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
1063
1064 // sanity, we cant have more than what's in one packet
1065 if (maxNumOfTMMBNBlocks > 200) {
1066 assert(false);
1067 rtcpParser.Iterate();
1068 return;
1069 }
1070
1071 ptrReceiveInfo->VerifyAndAllocateBoundingSet((uint32_t)maxNumOfTMMBNBlocks);
1072
1073 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1074 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode) {
1075 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
1076 pktType = rtcpParser.Iterate();
1077 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001078}
1079
1080// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001081void RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
1082 RTCPPacketInformation& rtcpPacketInformation) {
1083 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
1084 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001085}
1086
1087// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001088void RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
1089 const RTCPUtility::RTCPPacket& rtcpPacket) {
1090 receiveInfo.TmmbnBoundingSet.AddEntry(
1091 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
1092 rtcpPacket.TMMBNItem.MeasuredOverhead,
1093 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001094}
1095
1096// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001097void RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
1098 RTCPPacketInformation& rtcpPacketInformation) {
1099 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1100 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1101 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode) {
1102 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1103 pktType = rtcpParser.Iterate();
1104 }
1105}
1106
1107// no need for critsect we have _criticalSectionRTCPReceiver
1108void RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1109 RTCPPacketInformation& rtcpPacketInformation) {
1110 // in theory there could be multiple slices lost
1111 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1112 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
niklase@google.com470e71d2011-07-07 08:21:25 +00001113}
1114
1115void
1116RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1117 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1118{
1119 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001120 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1121 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1122 {
1123 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1124 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1125 {
1126 // to us unknown
1127 // continue
1128 rtcpParser.Iterate();
1129 return;
1130 }
1131 rtcpPacketInformation.rpsiPictureId = 0;
1132
1133 // convert NativeBitString to rpsiPictureId
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001134 uint8_t numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1135 for(uint8_t n = 0; n < (numberOfBytes-1); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001136 {
1137 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1138 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1139 }
1140 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1141 }
1142}
1143
1144// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001145void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1146 RTCPPacketInformation& rtcpPacketInformation) {
1147 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1148 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1149 pktType = rtcpParser.Iterate();
1150 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1151 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1152 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001153 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001154 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001155}
1156
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001157// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001158void RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1159 RTCPPacketInformation& rtcpPacketInformation) {
1160 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001161
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001162 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1163 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode) {
1164 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1165 pktType = rtcpParser.Iterate();
1166 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001167}
1168
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001169void RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1170 RTCPPacketInformation& rtcpPacketInformation) {
1171 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1172 rtcpPacketInformation.interArrivalJitter =
1173 rtcpPacket.ExtendedJitterReportItem.Jitter;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001174}
1175
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001176void RTCPReceiver::HandleREMBItem(
1177 RTCPUtility::RTCPParserV2& rtcpParser,
1178 RTCPPacketInformation& rtcpPacketInformation) {
1179 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1180 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1181 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1182 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001183}
1184
1185// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001186void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1187 RTCPPacketInformation& rtcpPacketInformation) {
1188 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1189 RTCPReceiveInformation* ptrReceiveInfo =
1190 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001191
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001192 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1193 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1194 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1195 pktType = rtcpParser.Iterate();
1196 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001197}
1198
1199// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001200void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1201 const RTCPUtility::RTCPPacket& rtcpPacket,
1202 RTCPPacketInformation& rtcpPacketInformation) {
1203 // Is it our sender that is requested to generate a new keyframe
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001204 if (main_ssrc_ != rtcpPacket.FIRItem.SSRC) {
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001205 return;
1206 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001207
1208 ++packet_type_counter_.fir_packets;
1209
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001210 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1211 // we don't know who this originate from
1212 if (receiveInfo) {
1213 // check if we have reported this FIRSequenceNumber before
1214 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1215 receiveInfo->lastFIRSequenceNumber) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001216 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001217 // sanity; don't go crazy with the callbacks
1218 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1219 receiveInfo->lastFIRRequest = now;
1220 receiveInfo->lastFIRSequenceNumber =
1221 rtcpPacket.FIRItem.CommandSequenceNumber;
1222 // received signal that we need to send a new key frame
1223 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1224 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001225 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001226 } else {
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}
1231
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001232void RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1233 RTCPPacketInformation& rtcpPacketInformation) {
1234 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001235
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001236 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1237 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1238 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
niklase@google.com470e71d2011-07-07 08:21:25 +00001239
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001240 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001241}
1242
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001243void RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1244 RTCPPacketInformation& rtcpPacketInformation) {
1245 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001246
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001247 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
niklase@google.com470e71d2011-07-07 08:21:25 +00001248
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001249 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001250}
1251
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001252int32_t RTCPReceiver::UpdateTMMBR() {
1253 int32_t numBoundingSet = 0;
1254 uint32_t bitrate = 0;
1255 uint32_t accNumCandidates = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001256
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001257 int32_t size = TMMBRReceived(0, 0, NULL);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001258 if (size > 0) {
1259 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1260 // Get candidate set from receiver.
1261 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1262 } else {
1263 // Candidate set empty.
1264 VerifyAndAllocateCandidateSet(0); // resets candidate set
1265 }
1266 // Find bounding set
1267 TMMBRSet* boundingSet = NULL;
1268 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1269 if (numBoundingSet == -1) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001270 LOG(LS_WARNING) << "Failed to find TMMBR bounding set.";
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001271 return -1;
1272 }
1273 // Set bounding set
1274 // Inform remote clients about the new bandwidth
1275 // inform the remote client
1276 _rtpRtcp.SetTMMBN(boundingSet);
1277
1278 // might trigger a TMMBN
1279 if (numBoundingSet == 0) {
1280 // owner of max bitrate request has timed out
1281 // empty bounding set has been sent
1282 return 0;
1283 }
1284 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001285 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001286 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001287 if (_cbRtcpBandwidthObserver) {
1288 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001289 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001290 }
1291 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001292}
1293
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001294void RTCPReceiver::RegisterRtcpStatisticsCallback(
1295 RtcpStatisticsCallback* callback) {
1296 CriticalSectionScoped cs(_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001297 stats_callback_ = callback;
1298}
1299
1300RtcpStatisticsCallback* RTCPReceiver::GetRtcpStatisticsCallback() {
1301 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1302 return stats_callback_;
1303}
1304
niklase@google.com470e71d2011-07-07 08:21:25 +00001305// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001306void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001307 RTCPPacketInformation& rtcpPacketInformation) {
1308 // Process TMMBR and REMB first to avoid multiple callbacks
1309 // to OnNetworkChanged.
1310 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001311 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1312 UpdateTMMBR();
1313 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001314 unsigned int local_ssrc = 0;
1315 {
1316 // We don't want to hold this critsect when triggering the callbacks below.
1317 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001318 local_ssrc = main_ssrc_;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001319 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001320 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1321 _rtpRtcp.OnRequestSendReport();
1322 }
1323 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001324 if (rtcpPacketInformation.nackSequenceNumbers.size() > 0) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001325 LOG(LS_VERBOSE) << "Incoming NACK length: "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001326 << rtcpPacketInformation.nackSequenceNumbers.size();
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001327 _rtpRtcp.OnReceivedNACK(rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001328 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001329 }
1330 {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001331 // We need feedback that we have received a report block(s) so that we
1332 // can generate a new packet in a conference relay scenario, one received
1333 // report can generate several RTCP packets, based on number relayed/mixed
1334 // a send report block should go out to all receivers.
1335 if (_cbRtcpIntraFrameObserver) {
1336 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1337 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1338 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001339 LOG(LS_VERBOSE) << "Incoming PLI from SSRC "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001340 << rtcpPacketInformation.remoteSSRC;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001341 } else {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001342 LOG(LS_VERBOSE) << "Incoming FIR from SSRC "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001343 << rtcpPacketInformation.remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001344 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001345 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001346 }
1347 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1348 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001349 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001350 }
1351 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1352 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001353 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001354 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001355 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001356 if (_cbRtcpBandwidthObserver) {
1357 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001358 LOG(LS_VERBOSE) << "Incoming REMB: "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001359 << rtcpPacketInformation.receiverEstimatedMaxBitrate;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001360 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1361 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1362 }
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001363 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1364 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001365 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001366 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001367 rtcpPacketInformation.report_blocks,
1368 rtcpPacketInformation.rtt,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001369 now);
1370 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001371 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001372 }
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001373
1374 {
1375 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1376 if (stats_callback_) {
1377 for (ReportBlockList::const_iterator it =
1378 rtcpPacketInformation.report_blocks.begin();
1379 it != rtcpPacketInformation.report_blocks.end();
1380 ++it) {
1381 RtcpStatistics stats;
1382 stats.cumulative_lost = it->cumulativeLost;
1383 stats.extended_max_sequence_number = it->extendedHighSeqNum;
1384 stats.fraction_lost = it->fractionLost;
1385 stats.jitter = it->jitter;
1386
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001387 stats_callback_->StatisticsUpdated(stats, it->sourceSSRC);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001388 }
1389 }
1390 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001391}
1392
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001393int32_t RTCPReceiver::CNAME(uint32_t remoteSSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001394 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001395 assert(cName);
1396
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001397 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1398 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001399 if (cnameInfo == NULL) {
1400 return -1;
1401 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001402 cName[RTCP_CNAME_SIZE - 1] = 0;
1403 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1404 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001405}
1406
1407// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001408int32_t RTCPReceiver::TMMBRReceived(uint32_t size,
1409 uint32_t accNumCandidates,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001410 TMMBRSet* candidateSet) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001411 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001412
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001413 std::map<uint32_t, RTCPReceiveInformation*>::const_iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001414 receiveInfoIt = _receivedInfoMap.begin();
1415 if (receiveInfoIt == _receivedInfoMap.end()) {
1416 return -1;
1417 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001418 uint32_t num = accNumCandidates;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001419 if (candidateSet) {
1420 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1421 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1422 if (receiveInfo == NULL) {
1423 return 0;
1424 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001425 for (uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001426 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001427 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001428 _clock->TimeInMilliseconds()) == 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001429 num++;
1430 }
1431 }
1432 receiveInfoIt++;
1433 }
1434 } else {
1435 while (receiveInfoIt != _receivedInfoMap.end()) {
1436 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1437 if(receiveInfo == NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001438 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001439 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001440 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001441 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001442 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001443 }
1444 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001445}
1446
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001447} // namespace webrtc