blob: 25a4756e6be69cab640b5a8309b578ff10e3cb3f [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 {
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000397 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "SR",
398 "remote_ssrc", remoteSSRC, "ssrc", main_ssrc_);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000399
niklase@google.com470e71d2011-07-07 08:21:25 +0000400 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
401 {
402 // only signal that we have received a SR when we accept one
403 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
404
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000405 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
406 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
407 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
408
niklase@google.com470e71d2011-07-07 08:21:25 +0000409 // We will only store the send report from one source, but
410 // we will store all the receive block
411
412 // Save the NTP time of this report
413 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
414 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
415 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
416 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
417 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
418
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000419 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000420 }
421 else
422 {
423 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
424 }
425 } else
426 {
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000427 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RR",
428 "remote_ssrc", remoteSSRC, "ssrc", main_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000429
430 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
431 }
432 UpdateReceiveInformation(*ptrReceiveInfo);
433
434 rtcpPacketType = rtcpParser.Iterate();
435
436 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
437 {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000438 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000439 rtcpPacketType = rtcpParser.Iterate();
440 }
441}
442
443// no need for critsect we have _criticalSectionRTCPReceiver
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000444void RTCPReceiver::HandleReportBlock(
445 const RTCPUtility::RTCPPacket& rtcpPacket,
446 RTCPPacketInformation& rtcpPacketInformation,
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000447 uint32_t remoteSSRC)
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000448 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000449 // This will be called once per report block in the RTCP packet.
450 // We filter out all report blocks that are not for us.
451 // Each packet has max 31 RR blocks.
452 //
453 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000454
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000455 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
456 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000457
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000458 // Filter out all report blocks that are not for us.
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000459 if (registered_ssrcs_.find(rtcpPacket.ReportBlockItem.SSRC) ==
460 registered_ssrcs_.end()) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000461 // This block is not for us ignore it.
462 return;
463 }
464
465 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
466 // _criticalSectionRTCPReceiver.
467 _criticalSectionRTCPReceiver->Leave();
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000468 int64_t sendTimeMS =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000469 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
470 _criticalSectionRTCPReceiver->Enter();
471
472 RTCPReportBlockInformation* reportBlock =
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000473 CreateOrGetReportBlockInformation(remoteSSRC,
474 rtcpPacket.ReportBlockItem.SSRC);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000475 if (reportBlock == NULL) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000476 LOG(LS_WARNING) << "Failed to CreateReportBlockInformation("
477 << remoteSSRC << ")";
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000478 return;
479 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000480
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000481 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000482 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
483 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
484 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
485 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
486 reportBlock->remoteReceiveBlock.cumulativeLost =
487 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000488 if (rb.ExtendedHighestSequenceNumber >
489 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
490 // We have successfully delivered new RTP packets to the remote side after
491 // the last RR was sent from the remote side.
492 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000493 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000494 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
495 rb.ExtendedHighestSequenceNumber;
496 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
497 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
498 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
499
500 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
501 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
502 }
503
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000504 uint32_t delaySinceLastSendReport =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000505 rtcpPacket.ReportBlockItem.DelayLastSR;
506
507 // local NTP time when we received this
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000508 uint32_t lastReceivedRRNTPsecs = 0;
509 uint32_t lastReceivedRRNTPfrac = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000510
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000511 _clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000512
513 // time when we received this in MS
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000514 int64_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
515 lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000516
517 // Estimate RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000518 uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000519 d /= 65536;
520 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
521
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000522 int64_t RTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000523
524 if (sendTimeMS > 0) {
525 RTT = receiveTimeMS - d - sendTimeMS;
526 if (RTT <= 0) {
527 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000528 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000529 if (RTT > reportBlock->maxRTT) {
530 // store max RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000531 reportBlock->maxRTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000532 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000533 if (reportBlock->minRTT == 0) {
534 // first RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000535 reportBlock->minRTT = RTT;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000536 } else if (RTT < reportBlock->minRTT) {
537 // Store min RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000538 reportBlock->minRTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000539 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000540 // store last RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000541 reportBlock->RTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000542
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000543 // store average RTT
544 if (reportBlock->numAverageCalcs != 0) {
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000545 float ac = static_cast<float>(reportBlock->numAverageCalcs);
546 float newAverage =
547 ((ac / (ac + 1)) * reportBlock->avgRTT) + ((1 / (ac + 1)) * RTT);
548 reportBlock->avgRTT = static_cast<int64_t>(newAverage + 0.5f);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000549 } else {
550 // first RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000551 reportBlock->avgRTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000552 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000553 reportBlock->numAverageCalcs++;
554 }
555
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000556 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RR_RTT", rb.SSRC,
557 RTT);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000558
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000559 rtcpPacketInformation.AddReportInfo(*reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000560}
561
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000562RTCPReportBlockInformation* RTCPReceiver::CreateOrGetReportBlockInformation(
563 uint32_t remote_ssrc,
564 uint32_t source_ssrc) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000565 RTCPReportBlockInformation* info =
566 GetReportBlockInformation(remote_ssrc, source_ssrc);
567 if (info == NULL) {
568 info = new RTCPReportBlockInformation;
569 _receivedReportBlockMap[source_ssrc][remote_ssrc] = info;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000570 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000571 return info;
niklase@google.com470e71d2011-07-07 08:21:25 +0000572}
573
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000574RTCPReportBlockInformation* RTCPReceiver::GetReportBlockInformation(
575 uint32_t remote_ssrc,
576 uint32_t source_ssrc) const {
577 ReportBlockMap::const_iterator it = _receivedReportBlockMap.find(source_ssrc);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000578 if (it == _receivedReportBlockMap.end()) {
579 return NULL;
580 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000581 const ReportBlockInfoMap* info_map = &(it->second);
582 ReportBlockInfoMap::const_iterator it_info = info_map->find(remote_ssrc);
583 if (it_info == info_map->end()) {
584 return NULL;
585 }
586 return it_info->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000587}
588
589RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000590RTCPReceiver::CreateCnameInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000591 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000592
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000593 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000594 _receivedCnameMap.find(remoteSSRC);
595
596 if (it != _receivedCnameMap.end()) {
597 return it->second;
598 }
599 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000600 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000601 _receivedCnameMap[remoteSSRC] = cnameInfo;
602 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000603}
604
605RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000606RTCPReceiver::GetCnameInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000607 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000608
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000609 std::map<uint32_t, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000610 _receivedCnameMap.find(remoteSSRC);
611
612 if (it == _receivedCnameMap.end()) {
613 return NULL;
614 }
615 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000616}
617
618RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000619RTCPReceiver::CreateReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000620 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000621
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000622 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000623 _receivedInfoMap.find(remoteSSRC);
624
625 if (it != _receivedInfoMap.end()) {
626 return it->second;
627 }
628 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
629 _receivedInfoMap[remoteSSRC] = receiveInfo;
630 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000631}
632
633RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000634RTCPReceiver::GetReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000635 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000636
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000637 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000638 _receivedInfoMap.find(remoteSSRC);
639 if (it == _receivedInfoMap.end()) {
640 return NULL;
641 }
642 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000643}
644
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000645void RTCPReceiver::UpdateReceiveInformation(
646 RTCPReceiveInformation& receiveInformation) {
647 // Update that this remote is alive
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000648 receiveInformation.lastTimeReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000649}
650
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000651bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
652 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
653 if (_lastReceivedRrMs == 0)
654 return false;
655
656 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000657 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000658 // Reset the timer to only trigger one log.
659 _lastReceivedRrMs = 0;
660 return true;
661 }
662 return false;
663}
664
665bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
666 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
667 if (_lastIncreasedSequenceNumberMs == 0)
668 return false;
669
670 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000671 if (_clock->TimeInMilliseconds() > _lastIncreasedSequenceNumberMs +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000672 time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000673 // Reset the timer to only trigger one log.
674 _lastIncreasedSequenceNumberMs = 0;
675 return true;
676 }
677 return false;
678}
679
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000680bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
681 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000682
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000683 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000684 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000685
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000686 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000687 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000688
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000689 while (receiveInfoIt != _receivedInfoMap.end()) {
690 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
691 if (receiveInfo == NULL) {
692 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000693 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000694 // time since last received rtcp packet
695 // when we dont have a lastTimeReceived and the object is marked
696 // readyForDelete it's removed from the map
697 if (receiveInfo->lastTimeReceived) {
698 /// use audio define since we don't know what interval the remote peer is
699 // using
700 if ((timeNow - receiveInfo->lastTimeReceived) >
701 5 * RTCP_INTERVAL_AUDIO_MS) {
702 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000703 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000704 // prevent that we call this over and over again
705 receiveInfo->lastTimeReceived = 0;
706 // send new TMMBN to all channels using the default codec
707 updateBoundingSet = true;
708 }
709 receiveInfoIt++;
710 } else if (receiveInfo->readyForDelete) {
711 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000712 std::map<uint32_t, RTCPReceiveInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000713 receiveInfoItemToBeErased = receiveInfoIt;
714 receiveInfoIt++;
715 delete receiveInfoItemToBeErased->second;
716 _receivedInfoMap.erase(receiveInfoItemToBeErased);
717 } else {
718 receiveInfoIt++;
719 }
720 }
721 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000722}
723
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000724int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000725 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000726
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000727 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000728 _receivedInfoMap.find(_remoteSSRC);
729
730 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000731 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000732 }
733 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
734 if (receiveInfo == NULL) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000735 return -1;
736 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000737 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000738 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000739 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000740 for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000741 i++) {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000742 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000743 // owner of bounding set
744 tmmbrOwner = true;
745 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000746 boundingSetRec->SetEntry(i,
747 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
748 receiveInfo->TmmbnBoundingSet.PacketOH(i),
749 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000750 }
751 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000752 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000753}
754
755// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000756void RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser) {
757 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
758 while (pktType == RTCPUtility::kRtcpSdesChunkCode) {
759 HandleSDESChunk(rtcpParser);
760 pktType = rtcpParser.Iterate();
761 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000762}
763
764// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000765void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
766 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
767 RTCPCnameInformation* cnameInfo =
768 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
769 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000770
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000771 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
772 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000773 if (stats_callback_ != NULL) {
774 stats_callback_->CNameChanged(rtcpPacket.CName.CName,
775 rtcpPacket.CName.SenderSSRC);
776 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000777}
778
779// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000780void RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
781 RTCPPacketInformation& rtcpPacketInformation) {
782 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
783 if (main_ssrc_ != rtcpPacket.NACK.MediaSSRC) {
784 // Not to us.
785 rtcpParser.Iterate();
786 return;
787 }
788 rtcpPacketInformation.ResetNACKPacketIdArray();
niklase@google.com470e71d2011-07-07 08:21:25 +0000789
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000790 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
791 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode) {
792 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
793 pktType = rtcpParser.Iterate();
794 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000795
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000796 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
797 ++packet_type_counter_.nack_packets;
798 packet_type_counter_.nack_requests = nack_stats_.requests();
799 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
800 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000801}
802
803// no need for critsect we have _criticalSectionRTCPReceiver
804void
805RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000806 RTCPPacketInformation& rtcpPacketInformation) {
807 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
808 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000809
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000810 uint16_t bitMask = rtcpPacket.NACKItem.BitMask;
811 if (bitMask) {
812 for (int i=1; i <= 16; ++i) {
813 if (bitMask & 0x01) {
814 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
815 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID + i);
816 }
817 bitMask = bitMask >>1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000818 }
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000819 }
820 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
niklase@google.com470e71d2011-07-07 08:21:25 +0000821}
822
823// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000824void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
825 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000826
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000827 // clear our lists
828 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000829 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
830 for (; it != _receivedReportBlockMap.end(); ++it) {
831 ReportBlockInfoMap* info_map = &(it->second);
832 ReportBlockInfoMap::iterator it_info = info_map->find(
833 rtcpPacket.BYE.SenderSSRC);
834 if (it_info != info_map->end()) {
835 delete it_info->second;
836 info_map->erase(it_info);
837 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000838 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000839
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000840 // we can't delete it due to TMMBR
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000841 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000842 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000843
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000844 if (receiveInfoIt != _receivedInfoMap.end()) {
845 receiveInfoIt->second->readyForDelete = true;
846 }
847
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000848 std::map<uint32_t, RTCPCnameInformation*>::iterator cnameInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000849 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
850
851 if (cnameInfoIt != _receivedCnameMap.end()) {
852 delete cnameInfoIt->second;
853 _receivedCnameMap.erase(cnameInfoIt);
854 }
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000855 xr_rr_rtt_ms_ = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000856 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000857}
858
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000859void RTCPReceiver::HandleXrHeader(
860 RTCPUtility::RTCPParserV2& parser,
861 RTCPPacketInformation& rtcpPacketInformation) {
862 const RTCPUtility::RTCPPacket& packet = parser.Packet();
863
864 rtcpPacketInformation.xr_originator_ssrc = packet.XR.OriginatorSSRC;
865
866 parser.Iterate();
867}
868
869void RTCPReceiver::HandleXrReceiveReferenceTime(
870 RTCPUtility::RTCPParserV2& parser,
871 RTCPPacketInformation& rtcpPacketInformation) {
872 const RTCPUtility::RTCPPacket& packet = parser.Packet();
873
874 _remoteXRReceiveTimeInfo.sourceSSRC =
875 rtcpPacketInformation.xr_originator_ssrc;
876
877 _remoteXRReceiveTimeInfo.lastRR = RTCPUtility::MidNtp(
878 packet.XRReceiverReferenceTimeItem.NTPMostSignificant,
879 packet.XRReceiverReferenceTimeItem.NTPLeastSignificant);
880
881 _clock->CurrentNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);
882
883 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
884
885 parser.Iterate();
886}
887
888void RTCPReceiver::HandleXrDlrrReportBlock(
889 RTCPUtility::RTCPParserV2& parser,
890 RTCPPacketInformation& rtcpPacketInformation) {
891 const RTCPUtility::RTCPPacket& packet = parser.Packet();
892 // Iterate through sub-block(s), if any.
893 RTCPUtility::RTCPPacketTypes packet_type = parser.Iterate();
894
895 while (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
896 HandleXrDlrrReportBlockItem(packet, rtcpPacketInformation);
897 packet_type = parser.Iterate();
898 }
899}
900
901void RTCPReceiver::HandleXrDlrrReportBlockItem(
902 const RTCPUtility::RTCPPacket& packet,
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000903 RTCPPacketInformation& rtcpPacketInformation)
904 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000905 if (registered_ssrcs_.find(packet.XRDLRRReportBlockItem.SSRC) ==
906 registered_ssrcs_.end()) {
907 // Not to us.
908 return;
909 }
910
911 rtcpPacketInformation.xr_dlrr_item = true;
912
913 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
914 // _criticalSectionRTCPReceiver.
915 _criticalSectionRTCPReceiver->Leave();
916
917 int64_t send_time_ms;
918 bool found = _rtpRtcp.SendTimeOfXrRrReport(
919 packet.XRDLRRReportBlockItem.LastRR, &send_time_ms);
920
921 _criticalSectionRTCPReceiver->Enter();
922
923 if (!found) {
924 return;
925 }
926
927 // The DelayLastRR field is in units of 1/65536 sec.
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000928 uint32_t delay_rr_ms =
929 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0x0000ffff) * 1000) >> 16) +
930 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0xffff0000) >> 16) * 1000);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000931
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000932 int64_t rtt = _clock->CurrentNtpInMilliseconds() - delay_rr_ms - send_time_ms;
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000933
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000934 xr_rr_rtt_ms_ = std::max<int64_t>(rtt, 1);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000935
936 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
937}
938
niklase@google.com470e71d2011-07-07 08:21:25 +0000939// no need for critsect we have _criticalSectionRTCPReceiver
940void
941RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
942 RTCPPacketInformation& rtcpPacketInformation)
943{
944 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
945
946 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
947
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000948 if(rtcpPacket.XRVOIPMetricItem.SSRC == main_ssrc_)
niklase@google.com470e71d2011-07-07 08:21:25 +0000949 {
950 // Store VoIP metrics block if it's about me
951 // from OriginatorSSRC do we filter it?
952 // rtcpPacket.XR.OriginatorSSRC;
953
954 RTCPVoIPMetric receivedVoIPMetrics;
955 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
956 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
957 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
958 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
959 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
960 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
961 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
962 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
963 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
964 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
965 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
966 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
967 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
968 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
969 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
970 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
971 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
972 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
973 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
974 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
975
976 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
977
978 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
979 }
980 rtcpParser.Iterate();
981}
982
983// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000984void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
985 RTCPPacketInformation& rtcpPacketInformation) {
986 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000987 if (main_ssrc_ == rtcpPacket.PLI.MediaSSRC) {
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000988 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "PLI");
justinlin@chromium.org7bfb3a32013-05-13 22:59:00 +0000989
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000990 ++packet_type_counter_.pli_packets;
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000991 // Received a signal that we need to send a new key frame.
992 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
993 }
994 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000995}
996
997// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000998void RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
999 RTCPPacketInformation& rtcpPacketInformation) {
1000 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001001
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001002 uint32_t senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
1003 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
1004 if (ptrReceiveInfo == NULL) {
1005 // This remote SSRC must be saved before.
1006 rtcpParser.Iterate();
1007 return;
1008 }
1009 if (rtcpPacket.TMMBR.MediaSSRC) {
1010 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
1011 // in relay mode this is a valid number
1012 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
1013 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001014
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001015 // Use packet length to calc max number of TMMBR blocks
1016 // each TMMBR block is 8 bytes
1017 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001018
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001019 // sanity, we can't have more than what's in one packet
1020 if (maxNumOfTMMBRBlocks > 200) {
1021 assert(false);
1022 rtcpParser.Iterate();
1023 return;
1024 }
1025 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((uint32_t)maxNumOfTMMBRBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001026
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001027 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1028 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode) {
1029 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
1030 pktType = rtcpParser.Iterate();
1031 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001032}
1033
1034// no need for critsect we have _criticalSectionRTCPReceiver
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001035void RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
1036 const RTCPUtility::RTCPPacket& rtcpPacket,
1037 RTCPPacketInformation& rtcpPacketInformation,
1038 uint32_t senderSSRC) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001039 if (main_ssrc_ == rtcpPacket.TMMBRItem.SSRC &&
1040 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0) {
1041 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
1042 _clock->TimeInMilliseconds());
1043 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
1044 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001045}
1046
1047// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001048void RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
1049 RTCPPacketInformation& rtcpPacketInformation) {
1050 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1051 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(
1052 rtcpPacket.TMMBN.SenderSSRC);
1053 if (ptrReceiveInfo == NULL) {
1054 // This remote SSRC must be saved before.
niklase@google.com470e71d2011-07-07 08:21:25 +00001055 rtcpParser.Iterate();
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001056 return;
1057 }
1058 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
1059 // Use packet length to calc max number of TMMBN blocks
1060 // each TMMBN block is 8 bytes
1061 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
1062
1063 // sanity, we cant have more than what's in one packet
1064 if (maxNumOfTMMBNBlocks > 200) {
1065 assert(false);
1066 rtcpParser.Iterate();
1067 return;
1068 }
1069
1070 ptrReceiveInfo->VerifyAndAllocateBoundingSet((uint32_t)maxNumOfTMMBNBlocks);
1071
1072 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1073 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode) {
1074 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
1075 pktType = rtcpParser.Iterate();
1076 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001077}
1078
1079// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001080void RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
1081 RTCPPacketInformation& rtcpPacketInformation) {
1082 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
1083 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001084}
1085
1086// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001087void RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
1088 const RTCPUtility::RTCPPacket& rtcpPacket) {
1089 receiveInfo.TmmbnBoundingSet.AddEntry(
1090 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
1091 rtcpPacket.TMMBNItem.MeasuredOverhead,
1092 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001093}
1094
1095// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001096void RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
1097 RTCPPacketInformation& rtcpPacketInformation) {
1098 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1099 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1100 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode) {
1101 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1102 pktType = rtcpParser.Iterate();
1103 }
1104}
1105
1106// no need for critsect we have _criticalSectionRTCPReceiver
1107void RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1108 RTCPPacketInformation& rtcpPacketInformation) {
1109 // in theory there could be multiple slices lost
1110 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1111 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
niklase@google.com470e71d2011-07-07 08:21:25 +00001112}
1113
1114void
1115RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1116 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1117{
1118 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001119 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1120 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1121 {
1122 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1123 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1124 {
1125 // to us unknown
1126 // continue
1127 rtcpParser.Iterate();
1128 return;
1129 }
1130 rtcpPacketInformation.rpsiPictureId = 0;
1131
1132 // convert NativeBitString to rpsiPictureId
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001133 uint8_t numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1134 for(uint8_t n = 0; n < (numberOfBytes-1); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001135 {
1136 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1137 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1138 }
1139 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1140 }
1141}
1142
1143// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001144void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1145 RTCPPacketInformation& rtcpPacketInformation) {
1146 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1147 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1148 pktType = rtcpParser.Iterate();
1149 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1150 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1151 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001152 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001153 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001154}
1155
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001156// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001157void RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1158 RTCPPacketInformation& rtcpPacketInformation) {
1159 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001160
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001161 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1162 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode) {
1163 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1164 pktType = rtcpParser.Iterate();
1165 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001166}
1167
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001168void RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1169 RTCPPacketInformation& rtcpPacketInformation) {
1170 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1171 rtcpPacketInformation.interArrivalJitter =
1172 rtcpPacket.ExtendedJitterReportItem.Jitter;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001173}
1174
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001175void RTCPReceiver::HandleREMBItem(
1176 RTCPUtility::RTCPParserV2& rtcpParser,
1177 RTCPPacketInformation& rtcpPacketInformation) {
1178 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1179 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1180 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1181 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001182}
1183
1184// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001185void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1186 RTCPPacketInformation& rtcpPacketInformation) {
1187 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1188 RTCPReceiveInformation* ptrReceiveInfo =
1189 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001190
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001191 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1192 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1193 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1194 pktType = rtcpParser.Iterate();
1195 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001196}
1197
1198// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001199void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1200 const RTCPUtility::RTCPPacket& rtcpPacket,
1201 RTCPPacketInformation& rtcpPacketInformation) {
1202 // Is it our sender that is requested to generate a new keyframe
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001203 if (main_ssrc_ != rtcpPacket.FIRItem.SSRC) {
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001204 return;
1205 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001206
1207 ++packet_type_counter_.fir_packets;
1208
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001209 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1210 // we don't know who this originate from
1211 if (receiveInfo) {
1212 // check if we have reported this FIRSequenceNumber before
1213 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1214 receiveInfo->lastFIRSequenceNumber) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001215 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001216 // sanity; don't go crazy with the callbacks
1217 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1218 receiveInfo->lastFIRRequest = now;
1219 receiveInfo->lastFIRSequenceNumber =
1220 rtcpPacket.FIRItem.CommandSequenceNumber;
1221 // received signal that we need to send a new key frame
1222 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1223 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001224 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001225 } else {
1226 // received signal that we need to send a new key frame
1227 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1228 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001229}
1230
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001231void RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1232 RTCPPacketInformation& rtcpPacketInformation) {
1233 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001234
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001235 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1236 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1237 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
niklase@google.com470e71d2011-07-07 08:21:25 +00001238
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001239 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001240}
1241
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001242void RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1243 RTCPPacketInformation& rtcpPacketInformation) {
1244 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001245
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001246 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
niklase@google.com470e71d2011-07-07 08:21:25 +00001247
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001248 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001249}
1250
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001251int32_t RTCPReceiver::UpdateTMMBR() {
1252 int32_t numBoundingSet = 0;
1253 uint32_t bitrate = 0;
1254 uint32_t accNumCandidates = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001255
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001256 int32_t size = TMMBRReceived(0, 0, NULL);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001257 if (size > 0) {
1258 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1259 // Get candidate set from receiver.
1260 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1261 } else {
1262 // Candidate set empty.
1263 VerifyAndAllocateCandidateSet(0); // resets candidate set
1264 }
1265 // Find bounding set
1266 TMMBRSet* boundingSet = NULL;
1267 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1268 if (numBoundingSet == -1) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001269 LOG(LS_WARNING) << "Failed to find TMMBR bounding set.";
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001270 return -1;
1271 }
1272 // Set bounding set
1273 // Inform remote clients about the new bandwidth
1274 // inform the remote client
1275 _rtpRtcp.SetTMMBN(boundingSet);
1276
1277 // might trigger a TMMBN
1278 if (numBoundingSet == 0) {
1279 // owner of max bitrate request has timed out
1280 // empty bounding set has been sent
1281 return 0;
1282 }
1283 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001284 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001285 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001286 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1287 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 {
1331 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001332
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001333 // We need feedback that we have received a report block(s) so that we
1334 // can generate a new packet in a conference relay scenario, one received
1335 // report can generate several RTCP packets, based on number relayed/mixed
1336 // a send report block should go out to all receivers.
1337 if (_cbRtcpIntraFrameObserver) {
1338 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1339 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1340 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001341 LOG(LS_VERBOSE) << "Incoming PLI from SSRC "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001342 << rtcpPacketInformation.remoteSSRC;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001343 } else {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001344 LOG(LS_VERBOSE) << "Incoming FIR from SSRC "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001345 << rtcpPacketInformation.remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001346 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001347 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001348 }
1349 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1350 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001351 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001352 }
1353 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1354 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001355 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001356 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001357 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001358 if (_cbRtcpBandwidthObserver) {
1359 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001360 LOG(LS_VERBOSE) << "Incoming REMB: "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001361 << rtcpPacketInformation.receiverEstimatedMaxBitrate;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001362 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1363 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1364 }
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001365 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1366 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001367 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001368 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001369 rtcpPacketInformation.report_blocks,
1370 rtcpPacketInformation.rtt,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001371 now);
1372 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001373 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001374 }
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001375
1376 {
1377 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1378 if (stats_callback_) {
1379 for (ReportBlockList::const_iterator it =
1380 rtcpPacketInformation.report_blocks.begin();
1381 it != rtcpPacketInformation.report_blocks.end();
1382 ++it) {
1383 RtcpStatistics stats;
1384 stats.cumulative_lost = it->cumulativeLost;
1385 stats.extended_max_sequence_number = it->extendedHighSeqNum;
1386 stats.fraction_lost = it->fractionLost;
1387 stats.jitter = it->jitter;
1388
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001389 stats_callback_->StatisticsUpdated(stats, it->sourceSSRC);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001390 }
1391 }
1392 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001393}
1394
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001395int32_t RTCPReceiver::CNAME(uint32_t remoteSSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001396 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001397 assert(cName);
1398
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001399 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1400 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001401 if (cnameInfo == NULL) {
1402 return -1;
1403 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001404 cName[RTCP_CNAME_SIZE - 1] = 0;
1405 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1406 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001407}
1408
1409// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001410int32_t RTCPReceiver::TMMBRReceived(uint32_t size,
1411 uint32_t accNumCandidates,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001412 TMMBRSet* candidateSet) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001413 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001414
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001415 std::map<uint32_t, RTCPReceiveInformation*>::const_iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001416 receiveInfoIt = _receivedInfoMap.begin();
1417 if (receiveInfoIt == _receivedInfoMap.end()) {
1418 return -1;
1419 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001420 uint32_t num = accNumCandidates;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001421 if (candidateSet) {
1422 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1423 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1424 if (receiveInfo == NULL) {
1425 return 0;
1426 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001427 for (uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001428 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001429 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001430 _clock->TimeInMilliseconds()) == 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001431 num++;
1432 }
1433 }
1434 receiveInfoIt++;
1435 }
1436 } else {
1437 while (receiveInfoIt != _receivedInfoMap.end()) {
1438 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1439 if(receiveInfo == NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001440 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001441 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001442 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001443 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001444 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001445 }
1446 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001447}
1448
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001449} // namespace webrtc