blob: 8dc728c1842af4732234e8a412f4a5c4b415a771 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_receiver.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> //assert
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000014#include <string.h> //memset
niklase@google.com470e71d2011-07-07 08:21:25 +000015
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000016#include <algorithm>
17
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000018#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
19#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
20#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000021#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000022#include "webrtc/system_wrappers/interface/trace_event.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000023
niklase@google.com470e71d2011-07-07 08:21:25 +000024namespace webrtc {
25using namespace RTCPUtility;
26using namespace RTCPHelp;
27
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000028// The number of RTCP time intervals needed to trigger a timeout.
29const int kRrTimeoutIntervals = 3;
30
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000031RTCPReceiver::RTCPReceiver(int32_t id, Clock* clock, ModuleRtpRtcpImpl* owner)
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000032 : TMMBRHelp(),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000033 _clock(clock),
34 _method(kRtcpOff),
35 _lastReceived(0),
36 _rtpRtcp(*owner),
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000037 _criticalSectionFeedbacks(
38 CriticalSectionWrapper::CreateCriticalSection()),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000039 _cbRtcpBandwidthObserver(NULL),
40 _cbRtcpIntraFrameObserver(NULL),
41 _criticalSectionRTCPReceiver(
42 CriticalSectionWrapper::CreateCriticalSection()),
43 main_ssrc_(0),
44 _remoteSSRC(0),
45 _remoteSenderInfo(),
46 _lastReceivedSRNTPsecs(0),
47 _lastReceivedSRNTPfrac(0),
48 _lastReceivedXRNTPsecs(0),
49 _lastReceivedXRNTPfrac(0),
50 xr_rr_rtt_ms_(0),
51 _receivedInfoMap(),
52 _packetTimeOutMS(0),
53 _lastReceivedRrMs(0),
54 _lastIncreasedSequenceNumberMs(0),
55 stats_callback_(NULL) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +000056 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
niklase@google.com470e71d2011-07-07 08:21:25 +000057}
58
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000059RTCPReceiver::~RTCPReceiver() {
60 delete _criticalSectionRTCPReceiver;
61 delete _criticalSectionFeedbacks;
niklase@google.com470e71d2011-07-07 08:21:25 +000062
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +000063 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
64 for (; it != _receivedReportBlockMap.end(); ++it) {
65 ReportBlockInfoMap* info_map = &(it->second);
66 while (!info_map->empty()) {
67 ReportBlockInfoMap::iterator it_info = info_map->begin();
68 delete it_info->second;
69 info_map->erase(it_info);
70 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000071 }
72 while (!_receivedInfoMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000073 std::map<uint32_t, RTCPReceiveInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000074 _receivedInfoMap.begin();
75 delete first->second;
76 _receivedInfoMap.erase(first);
77 }
78 while (!_receivedCnameMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000079 std::map<uint32_t, RTCPCnameInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000080 _receivedCnameMap.begin();
81 delete first->second;
82 _receivedCnameMap.erase(first);
83 }
niklase@google.com470e71d2011-07-07 08:21:25 +000084}
85
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +000086RTCPMethod RTCPReceiver::Status() const {
87 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
88 return _method;
niklase@google.com470e71d2011-07-07 08:21:25 +000089}
90
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000091void RTCPReceiver::SetRTCPStatus(RTCPMethod method) {
92 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
93 _method = method;
niklase@google.com470e71d2011-07-07 08:21:25 +000094}
95
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +000096int64_t RTCPReceiver::LastReceived() {
97 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
98 return _lastReceived;
niklase@google.com470e71d2011-07-07 08:21:25 +000099}
100
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000101int64_t RTCPReceiver::LastReceivedReceiverReport() const {
102 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
103 int64_t last_received_rr = -1;
104 for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin();
105 it != _receivedInfoMap.end(); ++it) {
106 if (it->second->lastTimeReceived > last_received_rr) {
107 last_received_rr = it->second->lastTimeReceived;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000108 }
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000109 }
110 return last_received_rr;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000111}
112
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000113void RTCPReceiver::SetRemoteSSRC(uint32_t ssrc) {
114 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000115
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000116 // new SSRC reset old reports
117 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
118 _lastReceivedSRNTPsecs = 0;
119 _lastReceivedSRNTPfrac = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000120
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000121 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000122}
123
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000124uint32_t RTCPReceiver::RemoteSSRC() const {
125 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
126 return _remoteSSRC;
127}
128
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000129void RTCPReceiver::RegisterRtcpObservers(
130 RtcpIntraFrameObserver* intra_frame_callback,
pbos@webrtc.orgece38902014-11-14 11:52:04 +0000131 RtcpBandwidthObserver* bandwidth_callback) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000132 CriticalSectionScoped lock(_criticalSectionFeedbacks);
133 _cbRtcpIntraFrameObserver = intra_frame_callback;
134 _cbRtcpBandwidthObserver = bandwidth_callback;
niklase@google.com470e71d2011-07-07 08:21:25 +0000135}
136
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000137void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
138 const std::set<uint32_t>& registered_ssrcs) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000139 uint32_t old_ssrc = 0;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000140 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000141 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000142 old_ssrc = main_ssrc_;
143 main_ssrc_ = main_ssrc;
144 registered_ssrcs_ = registered_ssrcs;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000145 }
146 {
147 CriticalSectionScoped lock(_criticalSectionFeedbacks);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000148 if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) {
149 _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc);
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000150 }
151 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000152}
153
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000154int32_t RTCPReceiver::RTT(uint32_t remoteSSRC,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000155 int64_t* RTT,
156 int64_t* avgRTT,
157 int64_t* minRTT,
158 int64_t* maxRTT) const {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000159 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000160
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000161 RTCPReportBlockInformation* reportBlock =
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000162 GetReportBlockInformation(remoteSSRC, main_ssrc_);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000163
164 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000165 return -1;
166 }
167 if (RTT) {
168 *RTT = reportBlock->RTT;
169 }
170 if (avgRTT) {
171 *avgRTT = reportBlock->avgRTT;
172 }
173 if (minRTT) {
174 *minRTT = reportBlock->minRTT;
175 }
176 if (maxRTT) {
177 *maxRTT = reportBlock->maxRTT;
178 }
179 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000180}
181
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000182bool RTCPReceiver::GetAndResetXrRrRtt(int64_t* rtt_ms) {
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000183 assert(rtt_ms);
184 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
185 if (xr_rr_rtt_ms_ == 0) {
186 return false;
187 }
188 *rtt_ms = xr_rr_rtt_ms_;
189 xr_rr_rtt_ms_ = 0;
190 return true;
191}
192
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000193// TODO(pbos): Make this fail when we haven't received NTP.
194bool RTCPReceiver::NTP(uint32_t* ReceivedNTPsecs,
195 uint32_t* ReceivedNTPfrac,
196 uint32_t* RTCPArrivalTimeSecs,
197 uint32_t* RTCPArrivalTimeFrac,
198 uint32_t* rtcp_timestamp) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000199{
200 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
201 if(ReceivedNTPsecs)
202 {
203 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
204 }
205 if(ReceivedNTPfrac)
206 {
207 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
208 }
209 if(RTCPArrivalTimeFrac)
210 {
211 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
212 }
213 if(RTCPArrivalTimeSecs)
214 {
215 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
216 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000217 if (rtcp_timestamp) {
218 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
219 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000220 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000221}
222
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000223bool RTCPReceiver::LastReceivedXrReferenceTimeInfo(
224 RtcpReceiveTimeInfo* info) const {
225 assert(info);
226 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
227 if (_lastReceivedXRNTPsecs == 0 && _lastReceivedXRNTPfrac == 0) {
228 return false;
229 }
230
231 info->sourceSSRC = _remoteXRReceiveTimeInfo.sourceSSRC;
232 info->lastRR = _remoteXRReceiveTimeInfo.lastRR;
233
234 // Get the delay since last received report (RFC 3611).
235 uint32_t receive_time = RTCPUtility::MidNtp(_lastReceivedXRNTPsecs,
236 _lastReceivedXRNTPfrac);
237
238 uint32_t ntp_sec = 0;
239 uint32_t ntp_frac = 0;
240 _clock->CurrentNtp(ntp_sec, ntp_frac);
241 uint32_t now = RTCPUtility::MidNtp(ntp_sec, ntp_frac);
242
243 info->delaySinceLastRR = now - receive_time;
244 return true;
245}
246
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000247int32_t RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const {
248 assert(senderInfo);
249 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
250 if (_lastReceivedSRNTPsecs == 0) {
251 return -1;
252 }
253 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
254 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000255}
256
257// statistics
258// we can get multiple receive reports when we receive the report from a CE
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000259int32_t RTCPReceiver::StatisticsReceived(
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000260 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000261 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000262 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000263 ReportBlockMap::const_iterator it = _receivedReportBlockMap.begin();
264 for (; it != _receivedReportBlockMap.end(); ++it) {
265 const ReportBlockInfoMap* info_map = &(it->second);
266 ReportBlockInfoMap::const_iterator it_info = info_map->begin();
267 for (; it_info != info_map->end(); ++it_info) {
268 receiveBlocks->push_back(it_info->second->remoteReceiveBlock);
269 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000270 }
271 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000272}
273
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000274void RTCPReceiver::GetPacketTypeCounter(
275 RtcpPacketTypeCounter* packet_counter) const {
276 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
277 *packet_counter = packet_type_counter_;
278}
279
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000280int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000281RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
282 RTCPUtility::RTCPParserV2* rtcpParser)
283{
284 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
285
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000286 _lastReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000287
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000288 if (packet_type_counter_.first_packet_time_ms == -1) {
289 packet_type_counter_.first_packet_time_ms = _lastReceived;
290 }
291
niklase@google.com470e71d2011-07-07 08:21:25 +0000292 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
293 while (pktType != RTCPUtility::kRtcpNotValidCode)
294 {
295 // Each "case" is responsible for iterate the parser to the
296 // next top level packet.
297 switch (pktType)
298 {
299 case RTCPUtility::kRtcpSrCode:
300 case RTCPUtility::kRtcpRrCode:
301 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
302 break;
303 case RTCPUtility::kRtcpSdesCode:
304 HandleSDES(*rtcpParser);
305 break;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000306 case RTCPUtility::kRtcpXrHeaderCode:
307 HandleXrHeader(*rtcpParser, rtcpPacketInformation);
308 break;
309 case RTCPUtility::kRtcpXrReceiverReferenceTimeCode:
310 HandleXrReceiveReferenceTime(*rtcpParser, rtcpPacketInformation);
311 break;
312 case RTCPUtility::kRtcpXrDlrrReportBlockCode:
313 HandleXrDlrrReportBlock(*rtcpParser, rtcpPacketInformation);
314 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000315 case RTCPUtility::kRtcpXrVoipMetricCode:
316 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
317 break;
318 case RTCPUtility::kRtcpByeCode:
319 HandleBYE(*rtcpParser);
320 break;
321 case RTCPUtility::kRtcpRtpfbNackCode:
322 HandleNACK(*rtcpParser, rtcpPacketInformation);
323 break;
324 case RTCPUtility::kRtcpRtpfbTmmbrCode:
325 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
326 break;
327 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000328 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000329 break;
330 case RTCPUtility::kRtcpRtpfbSrReqCode:
331 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
332 break;
333 case RTCPUtility::kRtcpPsfbPliCode:
334 HandlePLI(*rtcpParser, rtcpPacketInformation);
335 break;
336 case RTCPUtility::kRtcpPsfbSliCode:
337 HandleSLI(*rtcpParser, rtcpPacketInformation);
338 break;
339 case RTCPUtility::kRtcpPsfbRpsiCode:
340 HandleRPSI(*rtcpParser, rtcpPacketInformation);
341 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000342 case RTCPUtility::kRtcpExtendedIjCode:
343 HandleIJ(*rtcpParser, rtcpPacketInformation);
344 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000345 case RTCPUtility::kRtcpPsfbFirCode:
346 HandleFIR(*rtcpParser, rtcpPacketInformation);
347 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000348 case RTCPUtility::kRtcpPsfbAppCode:
349 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
350 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000351 case RTCPUtility::kRtcpAppCode:
352 // generic application messages
353 HandleAPP(*rtcpParser, rtcpPacketInformation);
354 break;
355 case RTCPUtility::kRtcpAppItemCode:
356 // generic application messages
357 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
358 break;
359 default:
360 rtcpParser->Iterate();
361 break;
362 }
363 pktType = rtcpParser->PacketType();
364 }
365 return 0;
366}
367
368// no need for critsect we have _criticalSectionRTCPReceiver
369void
370RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
371 RTCPPacketInformation& rtcpPacketInformation)
372{
373 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
374 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
375
376 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
377
378 // SR.SenderSSRC
379 // The synchronization source identifier for the originator of this SR packet
380
381 // rtcpPacket.RR.SenderSSRC
382 // The source of the packet sender, same as of SR? or is this a CE?
383
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000384 const uint32_t remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +0000385
386 rtcpPacketInformation.remoteSSRC = remoteSSRC;
387
388 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
389 if (!ptrReceiveInfo)
390 {
391 rtcpParser.Iterate();
392 return;
393 }
394
395 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
396 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000397 TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
398 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000399 "ssrc", main_ssrc_);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000400
niklase@google.com470e71d2011-07-07 08:21:25 +0000401 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
402 {
403 // only signal that we have received a SR when we accept one
404 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
405
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000406 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
407 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
408 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
409
niklase@google.com470e71d2011-07-07 08:21:25 +0000410 // We will only store the send report from one source, but
411 // we will store all the receive block
412
413 // Save the NTP time of this report
414 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
415 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
416 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
417 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
418 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
419
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000420 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000421 }
422 else
423 {
424 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
425 }
426 } else
427 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000428 TRACE_EVENT_INSTANT2("webrtc_rtp", "RR",
429 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000430 "ssrc", main_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000431
432 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
433 }
434 UpdateReceiveInformation(*ptrReceiveInfo);
435
436 rtcpPacketType = rtcpParser.Iterate();
437
438 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
439 {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000440 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000441 rtcpPacketType = rtcpParser.Iterate();
442 }
443}
444
445// no need for critsect we have _criticalSectionRTCPReceiver
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000446void RTCPReceiver::HandleReportBlock(
447 const RTCPUtility::RTCPPacket& rtcpPacket,
448 RTCPPacketInformation& rtcpPacketInformation,
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000449 uint32_t remoteSSRC)
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000450 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000451 // This will be called once per report block in the RTCP packet.
452 // We filter out all report blocks that are not for us.
453 // Each packet has max 31 RR blocks.
454 //
455 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000456
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000457 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
458 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000459
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000460 // Filter out all report blocks that are not for us.
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000461 if (registered_ssrcs_.find(rtcpPacket.ReportBlockItem.SSRC) ==
462 registered_ssrcs_.end()) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000463 // This block is not for us ignore it.
464 return;
465 }
466
467 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
468 // _criticalSectionRTCPReceiver.
469 _criticalSectionRTCPReceiver->Leave();
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000470 int64_t sendTimeMS =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000471 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
472 _criticalSectionRTCPReceiver->Enter();
473
474 RTCPReportBlockInformation* reportBlock =
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000475 CreateOrGetReportBlockInformation(remoteSSRC,
476 rtcpPacket.ReportBlockItem.SSRC);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000477 if (reportBlock == NULL) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000478 LOG(LS_WARNING) << "Failed to CreateReportBlockInformation("
479 << remoteSSRC << ")";
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000480 return;
481 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000482
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000483 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000484 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
485 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
486 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
487 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
488 reportBlock->remoteReceiveBlock.cumulativeLost =
489 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000490 if (rb.ExtendedHighestSequenceNumber >
491 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
492 // We have successfully delivered new RTP packets to the remote side after
493 // the last RR was sent from the remote side.
494 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000495 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000496 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
497 rb.ExtendedHighestSequenceNumber;
498 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
499 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
500 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
501
502 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
503 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
504 }
505
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000506 uint32_t delaySinceLastSendReport =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000507 rtcpPacket.ReportBlockItem.DelayLastSR;
508
509 // local NTP time when we received this
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000510 uint32_t lastReceivedRRNTPsecs = 0;
511 uint32_t lastReceivedRRNTPfrac = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000512
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000513 _clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000514
515 // time when we received this in MS
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000516 int64_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
517 lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000518
519 // Estimate RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000520 uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000521 d /= 65536;
522 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
523
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000524 int64_t RTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000525
526 if (sendTimeMS > 0) {
527 RTT = receiveTimeMS - d - sendTimeMS;
528 if (RTT <= 0) {
529 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000530 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000531 if (RTT > reportBlock->maxRTT) {
532 // store max RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000533 reportBlock->maxRTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000534 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000535 if (reportBlock->minRTT == 0) {
536 // first RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000537 reportBlock->minRTT = RTT;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000538 } else if (RTT < reportBlock->minRTT) {
539 // Store min RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000540 reportBlock->minRTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000541 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000542 // store last RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000543 reportBlock->RTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000544
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000545 // store average RTT
546 if (reportBlock->numAverageCalcs != 0) {
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000547 float ac = static_cast<float>(reportBlock->numAverageCalcs);
548 float newAverage =
549 ((ac / (ac + 1)) * reportBlock->avgRTT) + ((1 / (ac + 1)) * RTT);
550 reportBlock->avgRTT = static_cast<int64_t>(newAverage + 0.5f);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000551 } else {
552 // first RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000553 reportBlock->avgRTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000554 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000555 reportBlock->numAverageCalcs++;
556 }
557
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000558 TRACE_COUNTER_ID1("webrtc_rtp", "RR_RTT", rb.SSRC, RTT);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000559
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000560 rtcpPacketInformation.AddReportInfo(*reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000561}
562
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000563RTCPReportBlockInformation* RTCPReceiver::CreateOrGetReportBlockInformation(
564 uint32_t remote_ssrc,
565 uint32_t source_ssrc) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000566 RTCPReportBlockInformation* info =
567 GetReportBlockInformation(remote_ssrc, source_ssrc);
568 if (info == NULL) {
569 info = new RTCPReportBlockInformation;
570 _receivedReportBlockMap[source_ssrc][remote_ssrc] = info;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000571 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000572 return info;
niklase@google.com470e71d2011-07-07 08:21:25 +0000573}
574
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000575RTCPReportBlockInformation* RTCPReceiver::GetReportBlockInformation(
576 uint32_t remote_ssrc,
577 uint32_t source_ssrc) const {
578 ReportBlockMap::const_iterator it = _receivedReportBlockMap.find(source_ssrc);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000579 if (it == _receivedReportBlockMap.end()) {
580 return NULL;
581 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000582 const ReportBlockInfoMap* info_map = &(it->second);
583 ReportBlockInfoMap::const_iterator it_info = info_map->find(remote_ssrc);
584 if (it_info == info_map->end()) {
585 return NULL;
586 }
587 return it_info->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000588}
589
590RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000591RTCPReceiver::CreateCnameInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000592 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000593
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000594 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000595 _receivedCnameMap.find(remoteSSRC);
596
597 if (it != _receivedCnameMap.end()) {
598 return it->second;
599 }
600 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000601 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000602 _receivedCnameMap[remoteSSRC] = cnameInfo;
603 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000604}
605
606RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000607RTCPReceiver::GetCnameInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000608 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000609
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000610 std::map<uint32_t, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000611 _receivedCnameMap.find(remoteSSRC);
612
613 if (it == _receivedCnameMap.end()) {
614 return NULL;
615 }
616 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000617}
618
619RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000620RTCPReceiver::CreateReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000621 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000622
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000623 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000624 _receivedInfoMap.find(remoteSSRC);
625
626 if (it != _receivedInfoMap.end()) {
627 return it->second;
628 }
629 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
630 _receivedInfoMap[remoteSSRC] = receiveInfo;
631 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000632}
633
634RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000635RTCPReceiver::GetReceiveInformation(uint32_t remoteSSRC) {
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, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000639 _receivedInfoMap.find(remoteSSRC);
640 if (it == _receivedInfoMap.end()) {
641 return NULL;
642 }
643 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000644}
645
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000646void RTCPReceiver::UpdateReceiveInformation(
647 RTCPReceiveInformation& receiveInformation) {
648 // Update that this remote is alive
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000649 receiveInformation.lastTimeReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000650}
651
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000652bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
653 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
654 if (_lastReceivedRrMs == 0)
655 return false;
656
657 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000658 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000659 // Reset the timer to only trigger one log.
660 _lastReceivedRrMs = 0;
661 return true;
662 }
663 return false;
664}
665
666bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
667 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
668 if (_lastIncreasedSequenceNumberMs == 0)
669 return false;
670
671 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000672 if (_clock->TimeInMilliseconds() > _lastIncreasedSequenceNumberMs +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000673 time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000674 // Reset the timer to only trigger one log.
675 _lastIncreasedSequenceNumberMs = 0;
676 return true;
677 }
678 return false;
679}
680
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000681bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
682 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000683
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000684 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000685 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000686
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000687 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000688 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000689
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000690 while (receiveInfoIt != _receivedInfoMap.end()) {
691 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
692 if (receiveInfo == NULL) {
693 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000694 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000695 // time since last received rtcp packet
696 // when we dont have a lastTimeReceived and the object is marked
697 // readyForDelete it's removed from the map
698 if (receiveInfo->lastTimeReceived) {
699 /// use audio define since we don't know what interval the remote peer is
700 // using
701 if ((timeNow - receiveInfo->lastTimeReceived) >
702 5 * RTCP_INTERVAL_AUDIO_MS) {
703 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000704 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000705 // prevent that we call this over and over again
706 receiveInfo->lastTimeReceived = 0;
707 // send new TMMBN to all channels using the default codec
708 updateBoundingSet = true;
709 }
710 receiveInfoIt++;
711 } else if (receiveInfo->readyForDelete) {
712 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000713 std::map<uint32_t, RTCPReceiveInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000714 receiveInfoItemToBeErased = receiveInfoIt;
715 receiveInfoIt++;
716 delete receiveInfoItemToBeErased->second;
717 _receivedInfoMap.erase(receiveInfoItemToBeErased);
718 } else {
719 receiveInfoIt++;
720 }
721 }
722 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000723}
724
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000725int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000726 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000727
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000728 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000729 _receivedInfoMap.find(_remoteSSRC);
730
731 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000732 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000733 }
734 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
735 if (receiveInfo == NULL) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000736 return -1;
737 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000738 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000739 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000740 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000741 for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000742 i++) {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000743 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000744 // owner of bounding set
745 tmmbrOwner = true;
746 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000747 boundingSetRec->SetEntry(i,
748 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
749 receiveInfo->TmmbnBoundingSet.PacketOH(i),
750 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000751 }
752 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000753 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000754}
755
756// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000757void RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser) {
758 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
759 while (pktType == RTCPUtility::kRtcpSdesChunkCode) {
760 HandleSDESChunk(rtcpParser);
761 pktType = rtcpParser.Iterate();
762 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000763}
764
765// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000766void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
767 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
768 RTCPCnameInformation* cnameInfo =
769 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
770 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000771
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000772 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
773 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000774 if (stats_callback_ != NULL) {
775 stats_callback_->CNameChanged(rtcpPacket.CName.CName,
776 rtcpPacket.CName.SenderSSRC);
777 }
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) {
justinlin@chromium.org7bfb3a32013-05-13 22:59:00 +0000989 TRACE_EVENT_INSTANT0("webrtc_rtp", "PLI");
990
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 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1288 if (_cbRtcpBandwidthObserver) {
1289 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001290 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001291 }
1292 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001293}
1294
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001295void RTCPReceiver::RegisterRtcpStatisticsCallback(
1296 RtcpStatisticsCallback* callback) {
1297 CriticalSectionScoped cs(_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001298 stats_callback_ = callback;
1299}
1300
1301RtcpStatisticsCallback* RTCPReceiver::GetRtcpStatisticsCallback() {
1302 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1303 return stats_callback_;
1304}
1305
niklase@google.com470e71d2011-07-07 08:21:25 +00001306// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001307void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001308 RTCPPacketInformation& rtcpPacketInformation) {
1309 // Process TMMBR and REMB first to avoid multiple callbacks
1310 // to OnNetworkChanged.
1311 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001312 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1313 UpdateTMMBR();
1314 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001315 unsigned int local_ssrc = 0;
1316 {
1317 // We don't want to hold this critsect when triggering the callbacks below.
1318 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001319 local_ssrc = main_ssrc_;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001320 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001321 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1322 _rtpRtcp.OnRequestSendReport();
1323 }
1324 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001325 if (rtcpPacketInformation.nackSequenceNumbers.size() > 0) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001326 LOG(LS_VERBOSE) << "Incoming NACK length: "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001327 << rtcpPacketInformation.nackSequenceNumbers.size();
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001328 _rtpRtcp.OnReceivedNACK(rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001329 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001330 }
1331 {
1332 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001333
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001334 // We need feedback that we have received a report block(s) so that we
1335 // can generate a new packet in a conference relay scenario, one received
1336 // report can generate several RTCP packets, based on number relayed/mixed
1337 // a send report block should go out to all receivers.
1338 if (_cbRtcpIntraFrameObserver) {
1339 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1340 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1341 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001342 LOG(LS_VERBOSE) << "Incoming PLI from SSRC "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001343 << rtcpPacketInformation.remoteSSRC;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001344 } else {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001345 LOG(LS_VERBOSE) << "Incoming FIR from SSRC "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001346 << rtcpPacketInformation.remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001347 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001348 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001349 }
1350 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1351 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001352 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001353 }
1354 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1355 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001356 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001357 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001358 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001359 if (_cbRtcpBandwidthObserver) {
1360 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001361 LOG(LS_VERBOSE) << "Incoming REMB: "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001362 << rtcpPacketInformation.receiverEstimatedMaxBitrate;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001363 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1364 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1365 }
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001366 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1367 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001368 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001369 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001370 rtcpPacketInformation.report_blocks,
1371 rtcpPacketInformation.rtt,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001372 now);
1373 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001374 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001375 }
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001376
1377 {
1378 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1379 if (stats_callback_) {
1380 for (ReportBlockList::const_iterator it =
1381 rtcpPacketInformation.report_blocks.begin();
1382 it != rtcpPacketInformation.report_blocks.end();
1383 ++it) {
1384 RtcpStatistics stats;
1385 stats.cumulative_lost = it->cumulativeLost;
1386 stats.extended_max_sequence_number = it->extendedHighSeqNum;
1387 stats.fraction_lost = it->fractionLost;
1388 stats.jitter = it->jitter;
1389
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001390 stats_callback_->StatisticsUpdated(stats, it->sourceSSRC);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001391 }
1392 }
1393 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001394}
1395
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001396int32_t RTCPReceiver::CNAME(uint32_t remoteSSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001397 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001398 assert(cName);
1399
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001400 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1401 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001402 if (cnameInfo == NULL) {
1403 return -1;
1404 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001405 cName[RTCP_CNAME_SIZE - 1] = 0;
1406 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1407 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001408}
1409
1410// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001411int32_t RTCPReceiver::TMMBRReceived(uint32_t size,
1412 uint32_t accNumCandidates,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001413 TMMBRSet* candidateSet) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001414 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001415
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001416 std::map<uint32_t, RTCPReceiveInformation*>::const_iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001417 receiveInfoIt = _receivedInfoMap.begin();
1418 if (receiveInfoIt == _receivedInfoMap.end()) {
1419 return -1;
1420 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001421 uint32_t num = accNumCandidates;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001422 if (candidateSet) {
1423 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1424 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1425 if (receiveInfo == NULL) {
1426 return 0;
1427 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001428 for (uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001429 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001430 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001431 _clock->TimeInMilliseconds()) == 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001432 num++;
1433 }
1434 }
1435 receiveInfoIt++;
1436 }
1437 } else {
1438 while (receiveInfoIt != _receivedInfoMap.end()) {
1439 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1440 if(receiveInfo == NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001441 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001442 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001443 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001444 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001445 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001446 }
1447 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001448}
1449
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001450} // namespace webrtc