blob: b1b46dfcfe30ea438998a1a9e6ee749e7d2d8935 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_receiver.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> //assert
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000014#include <string.h> //memset
niklase@google.com470e71d2011-07-07 08:21:25 +000015
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000016#include <algorithm>
17
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000018#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
19#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
20#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000021#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000022#include "webrtc/system_wrappers/interface/trace_event.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000023
niklase@google.com470e71d2011-07-07 08:21:25 +000024namespace webrtc {
25using namespace RTCPUtility;
26using namespace RTCPHelp;
27
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000028// The number of RTCP time intervals needed to trigger a timeout.
29const int kRrTimeoutIntervals = 3;
30
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000031RTCPReceiver::RTCPReceiver(
32 int32_t id,
33 Clock* clock,
34 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
35 ModuleRtpRtcpImpl* owner)
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000036 : TMMBRHelp(),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000037 _clock(clock),
38 _method(kRtcpOff),
39 _lastReceived(0),
40 _rtpRtcp(*owner),
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000041 _criticalSectionFeedbacks(
42 CriticalSectionWrapper::CreateCriticalSection()),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000043 _cbRtcpBandwidthObserver(NULL),
44 _cbRtcpIntraFrameObserver(NULL),
45 _criticalSectionRTCPReceiver(
46 CriticalSectionWrapper::CreateCriticalSection()),
47 main_ssrc_(0),
48 _remoteSSRC(0),
49 _remoteSenderInfo(),
50 _lastReceivedSRNTPsecs(0),
51 _lastReceivedSRNTPfrac(0),
52 _lastReceivedXRNTPsecs(0),
53 _lastReceivedXRNTPfrac(0),
54 xr_rr_rtt_ms_(0),
55 _receivedInfoMap(),
56 _packetTimeOutMS(0),
57 _lastReceivedRrMs(0),
58 _lastIncreasedSequenceNumberMs(0),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000059 stats_callback_(NULL),
60 packet_type_counter_observer_(packet_type_counter_observer) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +000061 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
niklase@google.com470e71d2011-07-07 08:21:25 +000062}
63
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000064RTCPReceiver::~RTCPReceiver() {
65 delete _criticalSectionRTCPReceiver;
66 delete _criticalSectionFeedbacks;
niklase@google.com470e71d2011-07-07 08:21:25 +000067
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +000068 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
69 for (; it != _receivedReportBlockMap.end(); ++it) {
70 ReportBlockInfoMap* info_map = &(it->second);
71 while (!info_map->empty()) {
72 ReportBlockInfoMap::iterator it_info = info_map->begin();
73 delete it_info->second;
74 info_map->erase(it_info);
75 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000076 }
77 while (!_receivedInfoMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000078 std::map<uint32_t, RTCPReceiveInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000079 _receivedInfoMap.begin();
80 delete first->second;
81 _receivedInfoMap.erase(first);
82 }
83 while (!_receivedCnameMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000084 std::map<uint32_t, RTCPCnameInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000085 _receivedCnameMap.begin();
86 delete first->second;
87 _receivedCnameMap.erase(first);
88 }
niklase@google.com470e71d2011-07-07 08:21:25 +000089}
90
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +000091RTCPMethod RTCPReceiver::Status() const {
92 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
93 return _method;
niklase@google.com470e71d2011-07-07 08:21:25 +000094}
95
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000096void RTCPReceiver::SetRTCPStatus(RTCPMethod method) {
97 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
98 _method = method;
niklase@google.com470e71d2011-07-07 08:21:25 +000099}
100
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000101int64_t RTCPReceiver::LastReceived() {
102 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
103 return _lastReceived;
niklase@google.com470e71d2011-07-07 08:21:25 +0000104}
105
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000106int64_t RTCPReceiver::LastReceivedReceiverReport() const {
107 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
108 int64_t last_received_rr = -1;
109 for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin();
110 it != _receivedInfoMap.end(); ++it) {
111 if (it->second->lastTimeReceived > last_received_rr) {
112 last_received_rr = it->second->lastTimeReceived;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000113 }
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000114 }
115 return last_received_rr;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000116}
117
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000118void RTCPReceiver::SetRemoteSSRC(uint32_t ssrc) {
119 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000120
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000121 // new SSRC reset old reports
122 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
123 _lastReceivedSRNTPsecs = 0;
124 _lastReceivedSRNTPfrac = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000125
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000126 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000127}
128
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000129uint32_t RTCPReceiver::RemoteSSRC() const {
130 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
131 return _remoteSSRC;
132}
133
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000134void RTCPReceiver::RegisterRtcpObservers(
135 RtcpIntraFrameObserver* intra_frame_callback,
pbos@webrtc.orgece38902014-11-14 11:52:04 +0000136 RtcpBandwidthObserver* bandwidth_callback) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000137 CriticalSectionScoped lock(_criticalSectionFeedbacks);
138 _cbRtcpIntraFrameObserver = intra_frame_callback;
139 _cbRtcpBandwidthObserver = bandwidth_callback;
niklase@google.com470e71d2011-07-07 08:21:25 +0000140}
141
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000142void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
143 const std::set<uint32_t>& registered_ssrcs) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000144 uint32_t old_ssrc = 0;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000145 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000146 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000147 old_ssrc = main_ssrc_;
148 main_ssrc_ = main_ssrc;
149 registered_ssrcs_ = registered_ssrcs;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000150 }
151 {
152 CriticalSectionScoped lock(_criticalSectionFeedbacks);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000153 if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) {
154 _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc);
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000155 }
156 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000157}
158
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000159int32_t RTCPReceiver::RTT(uint32_t remoteSSRC,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000160 int64_t* RTT,
161 int64_t* avgRTT,
162 int64_t* minRTT,
163 int64_t* maxRTT) const {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000164 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000165
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000166 RTCPReportBlockInformation* reportBlock =
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000167 GetReportBlockInformation(remoteSSRC, main_ssrc_);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000168
169 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000170 return -1;
171 }
172 if (RTT) {
173 *RTT = reportBlock->RTT;
174 }
175 if (avgRTT) {
176 *avgRTT = reportBlock->avgRTT;
177 }
178 if (minRTT) {
179 *minRTT = reportBlock->minRTT;
180 }
181 if (maxRTT) {
182 *maxRTT = reportBlock->maxRTT;
183 }
184 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000185}
186
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000187bool RTCPReceiver::GetAndResetXrRrRtt(int64_t* rtt_ms) {
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000188 assert(rtt_ms);
189 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
190 if (xr_rr_rtt_ms_ == 0) {
191 return false;
192 }
193 *rtt_ms = xr_rr_rtt_ms_;
194 xr_rr_rtt_ms_ = 0;
195 return true;
196}
197
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000198// TODO(pbos): Make this fail when we haven't received NTP.
199bool RTCPReceiver::NTP(uint32_t* ReceivedNTPsecs,
200 uint32_t* ReceivedNTPfrac,
201 uint32_t* RTCPArrivalTimeSecs,
202 uint32_t* RTCPArrivalTimeFrac,
203 uint32_t* rtcp_timestamp) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000204{
205 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
206 if(ReceivedNTPsecs)
207 {
208 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
209 }
210 if(ReceivedNTPfrac)
211 {
212 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
213 }
214 if(RTCPArrivalTimeFrac)
215 {
216 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
217 }
218 if(RTCPArrivalTimeSecs)
219 {
220 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
221 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000222 if (rtcp_timestamp) {
223 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
224 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000225 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000226}
227
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000228bool RTCPReceiver::LastReceivedXrReferenceTimeInfo(
229 RtcpReceiveTimeInfo* info) const {
230 assert(info);
231 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
232 if (_lastReceivedXRNTPsecs == 0 && _lastReceivedXRNTPfrac == 0) {
233 return false;
234 }
235
236 info->sourceSSRC = _remoteXRReceiveTimeInfo.sourceSSRC;
237 info->lastRR = _remoteXRReceiveTimeInfo.lastRR;
238
239 // Get the delay since last received report (RFC 3611).
240 uint32_t receive_time = RTCPUtility::MidNtp(_lastReceivedXRNTPsecs,
241 _lastReceivedXRNTPfrac);
242
243 uint32_t ntp_sec = 0;
244 uint32_t ntp_frac = 0;
245 _clock->CurrentNtp(ntp_sec, ntp_frac);
246 uint32_t now = RTCPUtility::MidNtp(ntp_sec, ntp_frac);
247
248 info->delaySinceLastRR = now - receive_time;
249 return true;
250}
251
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000252int32_t RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const {
253 assert(senderInfo);
254 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
255 if (_lastReceivedSRNTPsecs == 0) {
256 return -1;
257 }
258 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
259 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000260}
261
262// statistics
263// we can get multiple receive reports when we receive the report from a CE
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000264int32_t RTCPReceiver::StatisticsReceived(
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000265 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000266 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000267 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000268 ReportBlockMap::const_iterator it = _receivedReportBlockMap.begin();
269 for (; it != _receivedReportBlockMap.end(); ++it) {
270 const ReportBlockInfoMap* info_map = &(it->second);
271 ReportBlockInfoMap::const_iterator it_info = info_map->begin();
272 for (; it_info != info_map->end(); ++it_info) {
273 receiveBlocks->push_back(it_info->second->remoteReceiveBlock);
274 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000275 }
276 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000277}
278
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000279int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000280RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
281 RTCPUtility::RTCPParserV2* rtcpParser)
282{
283 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
284
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000285 _lastReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000286
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000287 if (packet_type_counter_.first_packet_time_ms == -1) {
288 packet_type_counter_.first_packet_time_ms = _lastReceived;
289 }
290
niklase@google.com470e71d2011-07-07 08:21:25 +0000291 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
292 while (pktType != RTCPUtility::kRtcpNotValidCode)
293 {
294 // Each "case" is responsible for iterate the parser to the
295 // next top level packet.
296 switch (pktType)
297 {
298 case RTCPUtility::kRtcpSrCode:
299 case RTCPUtility::kRtcpRrCode:
300 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
301 break;
302 case RTCPUtility::kRtcpSdesCode:
303 HandleSDES(*rtcpParser);
304 break;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000305 case RTCPUtility::kRtcpXrHeaderCode:
306 HandleXrHeader(*rtcpParser, rtcpPacketInformation);
307 break;
308 case RTCPUtility::kRtcpXrReceiverReferenceTimeCode:
309 HandleXrReceiveReferenceTime(*rtcpParser, rtcpPacketInformation);
310 break;
311 case RTCPUtility::kRtcpXrDlrrReportBlockCode:
312 HandleXrDlrrReportBlock(*rtcpParser, rtcpPacketInformation);
313 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000314 case RTCPUtility::kRtcpXrVoipMetricCode:
315 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
316 break;
317 case RTCPUtility::kRtcpByeCode:
318 HandleBYE(*rtcpParser);
319 break;
320 case RTCPUtility::kRtcpRtpfbNackCode:
321 HandleNACK(*rtcpParser, rtcpPacketInformation);
322 break;
323 case RTCPUtility::kRtcpRtpfbTmmbrCode:
324 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
325 break;
326 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000327 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000328 break;
329 case RTCPUtility::kRtcpRtpfbSrReqCode:
330 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
331 break;
332 case RTCPUtility::kRtcpPsfbPliCode:
333 HandlePLI(*rtcpParser, rtcpPacketInformation);
334 break;
335 case RTCPUtility::kRtcpPsfbSliCode:
336 HandleSLI(*rtcpParser, rtcpPacketInformation);
337 break;
338 case RTCPUtility::kRtcpPsfbRpsiCode:
339 HandleRPSI(*rtcpParser, rtcpPacketInformation);
340 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000341 case RTCPUtility::kRtcpExtendedIjCode:
342 HandleIJ(*rtcpParser, rtcpPacketInformation);
343 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000344 case RTCPUtility::kRtcpPsfbFirCode:
345 HandleFIR(*rtcpParser, rtcpPacketInformation);
346 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000347 case RTCPUtility::kRtcpPsfbAppCode:
348 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
349 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000350 case RTCPUtility::kRtcpAppCode:
351 // generic application messages
352 HandleAPP(*rtcpParser, rtcpPacketInformation);
353 break;
354 case RTCPUtility::kRtcpAppItemCode:
355 // generic application messages
356 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
357 break;
358 default:
359 rtcpParser->Iterate();
360 break;
361 }
362 pktType = rtcpParser->PacketType();
363 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000364
365 if (packet_type_counter_observer_ != NULL) {
366 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
367 main_ssrc_, packet_type_counter_);
368 }
369
niklase@google.com470e71d2011-07-07 08:21:25 +0000370 return 0;
371}
372
373// no need for critsect we have _criticalSectionRTCPReceiver
374void
375RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
376 RTCPPacketInformation& rtcpPacketInformation)
377{
378 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
379 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
380
381 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
382
383 // SR.SenderSSRC
384 // The synchronization source identifier for the originator of this SR packet
385
386 // rtcpPacket.RR.SenderSSRC
387 // The source of the packet sender, same as of SR? or is this a CE?
388
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000389 const uint32_t remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +0000390
391 rtcpPacketInformation.remoteSSRC = remoteSSRC;
392
393 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
394 if (!ptrReceiveInfo)
395 {
396 rtcpParser.Iterate();
397 return;
398 }
399
400 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
401 {
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000402 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "SR",
403 "remote_ssrc", remoteSSRC, "ssrc", main_ssrc_);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000404
niklase@google.com470e71d2011-07-07 08:21:25 +0000405 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
406 {
407 // only signal that we have received a SR when we accept one
408 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
409
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000410 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
411 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
412 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
413
niklase@google.com470e71d2011-07-07 08:21:25 +0000414 // We will only store the send report from one source, but
415 // we will store all the receive block
416
417 // Save the NTP time of this report
418 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
419 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
420 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
421 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
422 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
423
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000424 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000425 }
426 else
427 {
428 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
429 }
430 } else
431 {
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000432 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RR",
433 "remote_ssrc", remoteSSRC, "ssrc", main_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000434
435 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
436 }
437 UpdateReceiveInformation(*ptrReceiveInfo);
438
439 rtcpPacketType = rtcpParser.Iterate();
440
441 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
442 {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000443 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000444 rtcpPacketType = rtcpParser.Iterate();
445 }
446}
447
448// no need for critsect we have _criticalSectionRTCPReceiver
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000449void RTCPReceiver::HandleReportBlock(
450 const RTCPUtility::RTCPPacket& rtcpPacket,
451 RTCPPacketInformation& rtcpPacketInformation,
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000452 uint32_t remoteSSRC)
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000453 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000454 // This will be called once per report block in the RTCP packet.
455 // We filter out all report blocks that are not for us.
456 // Each packet has max 31 RR blocks.
457 //
458 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000459
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000460 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
461 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000462
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000463 // Filter out all report blocks that are not for us.
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000464 if (registered_ssrcs_.find(rtcpPacket.ReportBlockItem.SSRC) ==
465 registered_ssrcs_.end()) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000466 // This block is not for us ignore it.
467 return;
468 }
469
470 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
471 // _criticalSectionRTCPReceiver.
472 _criticalSectionRTCPReceiver->Leave();
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000473 int64_t sendTimeMS =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000474 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
475 _criticalSectionRTCPReceiver->Enter();
476
477 RTCPReportBlockInformation* reportBlock =
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000478 CreateOrGetReportBlockInformation(remoteSSRC,
479 rtcpPacket.ReportBlockItem.SSRC);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000480 if (reportBlock == NULL) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000481 LOG(LS_WARNING) << "Failed to CreateReportBlockInformation("
482 << remoteSSRC << ")";
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000483 return;
484 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000485
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000486 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000487 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
488 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
489 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
490 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
491 reportBlock->remoteReceiveBlock.cumulativeLost =
492 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000493 if (rb.ExtendedHighestSequenceNumber >
494 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
495 // We have successfully delivered new RTP packets to the remote side after
496 // the last RR was sent from the remote side.
497 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000498 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000499 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
500 rb.ExtendedHighestSequenceNumber;
501 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
502 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
503 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
504
505 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
506 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
507 }
508
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000509 uint32_t delaySinceLastSendReport =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000510 rtcpPacket.ReportBlockItem.DelayLastSR;
511
512 // local NTP time when we received this
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000513 uint32_t lastReceivedRRNTPsecs = 0;
514 uint32_t lastReceivedRRNTPfrac = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000515
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000516 _clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000517
518 // time when we received this in MS
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000519 int64_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
520 lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000521
522 // Estimate RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000523 uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000524 d /= 65536;
525 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
526
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000527 int64_t RTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000528
529 if (sendTimeMS > 0) {
530 RTT = receiveTimeMS - d - sendTimeMS;
531 if (RTT <= 0) {
532 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000533 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000534 if (RTT > reportBlock->maxRTT) {
535 // store max RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000536 reportBlock->maxRTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000537 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000538 if (reportBlock->minRTT == 0) {
539 // first RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000540 reportBlock->minRTT = RTT;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000541 } else if (RTT < reportBlock->minRTT) {
542 // Store min RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000543 reportBlock->minRTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000544 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000545 // store last RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000546 reportBlock->RTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000547
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000548 // store average RTT
549 if (reportBlock->numAverageCalcs != 0) {
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000550 float ac = static_cast<float>(reportBlock->numAverageCalcs);
551 float newAverage =
552 ((ac / (ac + 1)) * reportBlock->avgRTT) + ((1 / (ac + 1)) * RTT);
553 reportBlock->avgRTT = static_cast<int64_t>(newAverage + 0.5f);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000554 } else {
555 // first RTT
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000556 reportBlock->avgRTT = RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000557 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000558 reportBlock->numAverageCalcs++;
559 }
560
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000561 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RR_RTT", rb.SSRC,
562 RTT);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000563
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000564 rtcpPacketInformation.AddReportInfo(*reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000565}
566
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000567RTCPReportBlockInformation* RTCPReceiver::CreateOrGetReportBlockInformation(
568 uint32_t remote_ssrc,
569 uint32_t source_ssrc) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000570 RTCPReportBlockInformation* info =
571 GetReportBlockInformation(remote_ssrc, source_ssrc);
572 if (info == NULL) {
573 info = new RTCPReportBlockInformation;
574 _receivedReportBlockMap[source_ssrc][remote_ssrc] = info;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000575 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000576 return info;
niklase@google.com470e71d2011-07-07 08:21:25 +0000577}
578
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000579RTCPReportBlockInformation* RTCPReceiver::GetReportBlockInformation(
580 uint32_t remote_ssrc,
581 uint32_t source_ssrc) const {
582 ReportBlockMap::const_iterator it = _receivedReportBlockMap.find(source_ssrc);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000583 if (it == _receivedReportBlockMap.end()) {
584 return NULL;
585 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000586 const ReportBlockInfoMap* info_map = &(it->second);
587 ReportBlockInfoMap::const_iterator it_info = info_map->find(remote_ssrc);
588 if (it_info == info_map->end()) {
589 return NULL;
590 }
591 return it_info->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000592}
593
594RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000595RTCPReceiver::CreateCnameInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000596 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000597
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000598 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000599 _receivedCnameMap.find(remoteSSRC);
600
601 if (it != _receivedCnameMap.end()) {
602 return it->second;
603 }
604 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000605 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000606 _receivedCnameMap[remoteSSRC] = cnameInfo;
607 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000608}
609
610RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000611RTCPReceiver::GetCnameInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000612 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000613
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000614 std::map<uint32_t, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000615 _receivedCnameMap.find(remoteSSRC);
616
617 if (it == _receivedCnameMap.end()) {
618 return NULL;
619 }
620 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000621}
622
623RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000624RTCPReceiver::CreateReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000625 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000626
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000627 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000628 _receivedInfoMap.find(remoteSSRC);
629
630 if (it != _receivedInfoMap.end()) {
631 return it->second;
632 }
633 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
634 _receivedInfoMap[remoteSSRC] = receiveInfo;
635 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000636}
637
638RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000639RTCPReceiver::GetReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000640 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000641
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000642 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000643 _receivedInfoMap.find(remoteSSRC);
644 if (it == _receivedInfoMap.end()) {
645 return NULL;
646 }
647 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000648}
649
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000650void RTCPReceiver::UpdateReceiveInformation(
651 RTCPReceiveInformation& receiveInformation) {
652 // Update that this remote is alive
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000653 receiveInformation.lastTimeReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000654}
655
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000656bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
657 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
658 if (_lastReceivedRrMs == 0)
659 return false;
660
661 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000662 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000663 // Reset the timer to only trigger one log.
664 _lastReceivedRrMs = 0;
665 return true;
666 }
667 return false;
668}
669
670bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
671 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
672 if (_lastIncreasedSequenceNumberMs == 0)
673 return false;
674
675 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000676 if (_clock->TimeInMilliseconds() > _lastIncreasedSequenceNumberMs +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000677 time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000678 // Reset the timer to only trigger one log.
679 _lastIncreasedSequenceNumberMs = 0;
680 return true;
681 }
682 return false;
683}
684
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000685bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
686 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000687
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000688 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000689 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000690
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000691 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000692 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000693
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000694 while (receiveInfoIt != _receivedInfoMap.end()) {
695 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
696 if (receiveInfo == NULL) {
697 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000698 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000699 // time since last received rtcp packet
700 // when we dont have a lastTimeReceived and the object is marked
701 // readyForDelete it's removed from the map
702 if (receiveInfo->lastTimeReceived) {
703 /// use audio define since we don't know what interval the remote peer is
704 // using
705 if ((timeNow - receiveInfo->lastTimeReceived) >
706 5 * RTCP_INTERVAL_AUDIO_MS) {
707 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000708 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000709 // prevent that we call this over and over again
710 receiveInfo->lastTimeReceived = 0;
711 // send new TMMBN to all channels using the default codec
712 updateBoundingSet = true;
713 }
714 receiveInfoIt++;
715 } else if (receiveInfo->readyForDelete) {
716 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000717 std::map<uint32_t, RTCPReceiveInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000718 receiveInfoItemToBeErased = receiveInfoIt;
719 receiveInfoIt++;
720 delete receiveInfoItemToBeErased->second;
721 _receivedInfoMap.erase(receiveInfoItemToBeErased);
722 } else {
723 receiveInfoIt++;
724 }
725 }
726 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000727}
728
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000729int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000730 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000731
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000732 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000733 _receivedInfoMap.find(_remoteSSRC);
734
735 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000736 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000737 }
738 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
739 if (receiveInfo == NULL) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000740 return -1;
741 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000742 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000743 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000744 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000745 for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000746 i++) {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000747 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000748 // owner of bounding set
749 tmmbrOwner = true;
750 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000751 boundingSetRec->SetEntry(i,
752 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
753 receiveInfo->TmmbnBoundingSet.PacketOH(i),
754 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000755 }
756 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000757 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000758}
759
760// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000761void RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser) {
762 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
763 while (pktType == RTCPUtility::kRtcpSdesChunkCode) {
764 HandleSDESChunk(rtcpParser);
765 pktType = rtcpParser.Iterate();
766 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000767}
768
769// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000770void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
771 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
772 RTCPCnameInformation* cnameInfo =
773 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
774 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000775
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000776 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
777 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000778 {
779 CriticalSectionScoped lock(_criticalSectionFeedbacks);
780 if (stats_callback_ != NULL) {
781 stats_callback_->CNameChanged(rtcpPacket.CName.CName,
782 rtcpPacket.CName.SenderSSRC);
783 }
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000784 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000785}
786
787// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000788void RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
789 RTCPPacketInformation& rtcpPacketInformation) {
790 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
791 if (main_ssrc_ != rtcpPacket.NACK.MediaSSRC) {
792 // Not to us.
793 rtcpParser.Iterate();
794 return;
795 }
796 rtcpPacketInformation.ResetNACKPacketIdArray();
niklase@google.com470e71d2011-07-07 08:21:25 +0000797
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000798 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
799 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode) {
800 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
801 pktType = rtcpParser.Iterate();
802 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000803
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000804 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
805 ++packet_type_counter_.nack_packets;
806 packet_type_counter_.nack_requests = nack_stats_.requests();
807 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
808 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000809}
810
811// no need for critsect we have _criticalSectionRTCPReceiver
812void
813RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000814 RTCPPacketInformation& rtcpPacketInformation) {
815 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
816 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000817
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000818 uint16_t bitMask = rtcpPacket.NACKItem.BitMask;
819 if (bitMask) {
820 for (int i=1; i <= 16; ++i) {
821 if (bitMask & 0x01) {
822 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
823 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID + i);
824 }
825 bitMask = bitMask >>1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000826 }
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000827 }
828 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
niklase@google.com470e71d2011-07-07 08:21:25 +0000829}
830
831// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000832void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
833 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000834
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000835 // clear our lists
836 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000837 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
838 for (; it != _receivedReportBlockMap.end(); ++it) {
839 ReportBlockInfoMap* info_map = &(it->second);
840 ReportBlockInfoMap::iterator it_info = info_map->find(
841 rtcpPacket.BYE.SenderSSRC);
842 if (it_info != info_map->end()) {
843 delete it_info->second;
844 info_map->erase(it_info);
845 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000846 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000847
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000848 // we can't delete it due to TMMBR
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000849 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000850 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000851
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000852 if (receiveInfoIt != _receivedInfoMap.end()) {
853 receiveInfoIt->second->readyForDelete = true;
854 }
855
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000856 std::map<uint32_t, RTCPCnameInformation*>::iterator cnameInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000857 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
858
859 if (cnameInfoIt != _receivedCnameMap.end()) {
860 delete cnameInfoIt->second;
861 _receivedCnameMap.erase(cnameInfoIt);
862 }
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000863 xr_rr_rtt_ms_ = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000864 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000865}
866
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000867void RTCPReceiver::HandleXrHeader(
868 RTCPUtility::RTCPParserV2& parser,
869 RTCPPacketInformation& rtcpPacketInformation) {
870 const RTCPUtility::RTCPPacket& packet = parser.Packet();
871
872 rtcpPacketInformation.xr_originator_ssrc = packet.XR.OriginatorSSRC;
873
874 parser.Iterate();
875}
876
877void RTCPReceiver::HandleXrReceiveReferenceTime(
878 RTCPUtility::RTCPParserV2& parser,
879 RTCPPacketInformation& rtcpPacketInformation) {
880 const RTCPUtility::RTCPPacket& packet = parser.Packet();
881
882 _remoteXRReceiveTimeInfo.sourceSSRC =
883 rtcpPacketInformation.xr_originator_ssrc;
884
885 _remoteXRReceiveTimeInfo.lastRR = RTCPUtility::MidNtp(
886 packet.XRReceiverReferenceTimeItem.NTPMostSignificant,
887 packet.XRReceiverReferenceTimeItem.NTPLeastSignificant);
888
889 _clock->CurrentNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);
890
891 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
892
893 parser.Iterate();
894}
895
896void RTCPReceiver::HandleXrDlrrReportBlock(
897 RTCPUtility::RTCPParserV2& parser,
898 RTCPPacketInformation& rtcpPacketInformation) {
899 const RTCPUtility::RTCPPacket& packet = parser.Packet();
900 // Iterate through sub-block(s), if any.
901 RTCPUtility::RTCPPacketTypes packet_type = parser.Iterate();
902
903 while (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
904 HandleXrDlrrReportBlockItem(packet, rtcpPacketInformation);
905 packet_type = parser.Iterate();
906 }
907}
908
909void RTCPReceiver::HandleXrDlrrReportBlockItem(
910 const RTCPUtility::RTCPPacket& packet,
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000911 RTCPPacketInformation& rtcpPacketInformation)
912 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000913 if (registered_ssrcs_.find(packet.XRDLRRReportBlockItem.SSRC) ==
914 registered_ssrcs_.end()) {
915 // Not to us.
916 return;
917 }
918
919 rtcpPacketInformation.xr_dlrr_item = true;
920
921 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
922 // _criticalSectionRTCPReceiver.
923 _criticalSectionRTCPReceiver->Leave();
924
925 int64_t send_time_ms;
926 bool found = _rtpRtcp.SendTimeOfXrRrReport(
927 packet.XRDLRRReportBlockItem.LastRR, &send_time_ms);
928
929 _criticalSectionRTCPReceiver->Enter();
930
931 if (!found) {
932 return;
933 }
934
935 // The DelayLastRR field is in units of 1/65536 sec.
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000936 uint32_t delay_rr_ms =
937 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0x0000ffff) * 1000) >> 16) +
938 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0xffff0000) >> 16) * 1000);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000939
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000940 int64_t rtt = _clock->CurrentNtpInMilliseconds() - delay_rr_ms - send_time_ms;
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000941
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000942 xr_rr_rtt_ms_ = std::max<int64_t>(rtt, 1);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000943
944 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
945}
946
niklase@google.com470e71d2011-07-07 08:21:25 +0000947// no need for critsect we have _criticalSectionRTCPReceiver
948void
949RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
950 RTCPPacketInformation& rtcpPacketInformation)
951{
952 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
953
954 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
955
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000956 if(rtcpPacket.XRVOIPMetricItem.SSRC == main_ssrc_)
niklase@google.com470e71d2011-07-07 08:21:25 +0000957 {
958 // Store VoIP metrics block if it's about me
959 // from OriginatorSSRC do we filter it?
960 // rtcpPacket.XR.OriginatorSSRC;
961
962 RTCPVoIPMetric receivedVoIPMetrics;
963 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
964 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
965 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
966 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
967 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
968 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
969 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
970 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
971 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
972 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
973 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
974 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
975 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
976 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
977 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
978 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
979 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
980 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
981 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
982 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
983
984 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
985
986 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
987 }
988 rtcpParser.Iterate();
989}
990
991// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000992void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
993 RTCPPacketInformation& rtcpPacketInformation) {
994 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000995 if (main_ssrc_ == rtcpPacket.PLI.MediaSSRC) {
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000996 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "PLI");
justinlin@chromium.org7bfb3a32013-05-13 22:59:00 +0000997
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000998 ++packet_type_counter_.pli_packets;
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000999 // Received a signal that we need to send a new key frame.
1000 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
1001 }
1002 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001003}
1004
1005// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001006void RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
1007 RTCPPacketInformation& rtcpPacketInformation) {
1008 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001009
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001010 uint32_t senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
1011 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
1012 if (ptrReceiveInfo == NULL) {
1013 // This remote SSRC must be saved before.
1014 rtcpParser.Iterate();
1015 return;
1016 }
1017 if (rtcpPacket.TMMBR.MediaSSRC) {
1018 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
1019 // in relay mode this is a valid number
1020 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
1021 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001022
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001023 // Use packet length to calc max number of TMMBR blocks
1024 // each TMMBR block is 8 bytes
1025 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001026
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001027 // sanity, we can't have more than what's in one packet
1028 if (maxNumOfTMMBRBlocks > 200) {
1029 assert(false);
1030 rtcpParser.Iterate();
1031 return;
1032 }
1033 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((uint32_t)maxNumOfTMMBRBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001034
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001035 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1036 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode) {
1037 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
1038 pktType = rtcpParser.Iterate();
1039 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001040}
1041
1042// no need for critsect we have _criticalSectionRTCPReceiver
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001043void RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
1044 const RTCPUtility::RTCPPacket& rtcpPacket,
1045 RTCPPacketInformation& rtcpPacketInformation,
1046 uint32_t senderSSRC) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001047 if (main_ssrc_ == rtcpPacket.TMMBRItem.SSRC &&
1048 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0) {
1049 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
1050 _clock->TimeInMilliseconds());
1051 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
1052 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001053}
1054
1055// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001056void RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
1057 RTCPPacketInformation& rtcpPacketInformation) {
1058 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1059 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(
1060 rtcpPacket.TMMBN.SenderSSRC);
1061 if (ptrReceiveInfo == NULL) {
1062 // This remote SSRC must be saved before.
niklase@google.com470e71d2011-07-07 08:21:25 +00001063 rtcpParser.Iterate();
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001064 return;
1065 }
1066 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
1067 // Use packet length to calc max number of TMMBN blocks
1068 // each TMMBN block is 8 bytes
1069 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
1070
1071 // sanity, we cant have more than what's in one packet
1072 if (maxNumOfTMMBNBlocks > 200) {
1073 assert(false);
1074 rtcpParser.Iterate();
1075 return;
1076 }
1077
1078 ptrReceiveInfo->VerifyAndAllocateBoundingSet((uint32_t)maxNumOfTMMBNBlocks);
1079
1080 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1081 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode) {
1082 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
1083 pktType = rtcpParser.Iterate();
1084 }
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::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
1089 RTCPPacketInformation& rtcpPacketInformation) {
1090 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
1091 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001092}
1093
1094// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001095void RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
1096 const RTCPUtility::RTCPPacket& rtcpPacket) {
1097 receiveInfo.TmmbnBoundingSet.AddEntry(
1098 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
1099 rtcpPacket.TMMBNItem.MeasuredOverhead,
1100 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001101}
1102
1103// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001104void RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
1105 RTCPPacketInformation& rtcpPacketInformation) {
1106 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1107 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1108 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode) {
1109 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1110 pktType = rtcpParser.Iterate();
1111 }
1112}
1113
1114// no need for critsect we have _criticalSectionRTCPReceiver
1115void RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1116 RTCPPacketInformation& rtcpPacketInformation) {
1117 // in theory there could be multiple slices lost
1118 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1119 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
niklase@google.com470e71d2011-07-07 08:21:25 +00001120}
1121
1122void
1123RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1124 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1125{
1126 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001127 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1128 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1129 {
1130 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1131 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1132 {
1133 // to us unknown
1134 // continue
1135 rtcpParser.Iterate();
1136 return;
1137 }
1138 rtcpPacketInformation.rpsiPictureId = 0;
1139
1140 // convert NativeBitString to rpsiPictureId
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001141 uint8_t numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1142 for(uint8_t n = 0; n < (numberOfBytes-1); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001143 {
1144 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1145 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1146 }
1147 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1148 }
1149}
1150
1151// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001152void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1153 RTCPPacketInformation& rtcpPacketInformation) {
1154 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1155 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1156 pktType = rtcpParser.Iterate();
1157 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1158 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1159 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001160 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001161 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001162}
1163
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001164// no need for critsect we have _criticalSectionRTCPReceiver
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001165void RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1166 RTCPPacketInformation& rtcpPacketInformation) {
1167 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001168
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001169 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1170 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode) {
1171 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1172 pktType = rtcpParser.Iterate();
1173 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001174}
1175
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001176void RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1177 RTCPPacketInformation& rtcpPacketInformation) {
1178 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1179 rtcpPacketInformation.interArrivalJitter =
1180 rtcpPacket.ExtendedJitterReportItem.Jitter;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001181}
1182
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001183void RTCPReceiver::HandleREMBItem(
1184 RTCPUtility::RTCPParserV2& rtcpParser,
1185 RTCPPacketInformation& rtcpPacketInformation) {
1186 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1187 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1188 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1189 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001190}
1191
1192// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001193void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1194 RTCPPacketInformation& rtcpPacketInformation) {
1195 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1196 RTCPReceiveInformation* ptrReceiveInfo =
1197 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001198
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001199 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1200 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1201 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1202 pktType = rtcpParser.Iterate();
1203 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001204}
1205
1206// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001207void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1208 const RTCPUtility::RTCPPacket& rtcpPacket,
1209 RTCPPacketInformation& rtcpPacketInformation) {
1210 // Is it our sender that is requested to generate a new keyframe
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001211 if (main_ssrc_ != rtcpPacket.FIRItem.SSRC) {
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001212 return;
1213 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001214
1215 ++packet_type_counter_.fir_packets;
1216
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001217 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1218 // we don't know who this originate from
1219 if (receiveInfo) {
1220 // check if we have reported this FIRSequenceNumber before
1221 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1222 receiveInfo->lastFIRSequenceNumber) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001223 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001224 // sanity; don't go crazy with the callbacks
1225 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1226 receiveInfo->lastFIRRequest = now;
1227 receiveInfo->lastFIRSequenceNumber =
1228 rtcpPacket.FIRItem.CommandSequenceNumber;
1229 // received signal that we need to send a new key frame
1230 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1231 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001232 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001233 } else {
1234 // received signal that we need to send a new key frame
1235 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1236 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001237}
1238
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001239void RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1240 RTCPPacketInformation& rtcpPacketInformation) {
1241 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001242
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001243 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1244 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1245 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
niklase@google.com470e71d2011-07-07 08:21:25 +00001246
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001247 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001248}
1249
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001250void RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1251 RTCPPacketInformation& rtcpPacketInformation) {
1252 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001253
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001254 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
niklase@google.com470e71d2011-07-07 08:21:25 +00001255
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001256 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001257}
1258
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001259int32_t RTCPReceiver::UpdateTMMBR() {
1260 int32_t numBoundingSet = 0;
1261 uint32_t bitrate = 0;
1262 uint32_t accNumCandidates = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001263
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001264 int32_t size = TMMBRReceived(0, 0, NULL);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001265 if (size > 0) {
1266 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1267 // Get candidate set from receiver.
1268 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1269 } else {
1270 // Candidate set empty.
1271 VerifyAndAllocateCandidateSet(0); // resets candidate set
1272 }
1273 // Find bounding set
1274 TMMBRSet* boundingSet = NULL;
1275 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1276 if (numBoundingSet == -1) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001277 LOG(LS_WARNING) << "Failed to find TMMBR bounding set.";
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001278 return -1;
1279 }
1280 // Set bounding set
1281 // Inform remote clients about the new bandwidth
1282 // inform the remote client
1283 _rtpRtcp.SetTMMBN(boundingSet);
1284
1285 // might trigger a TMMBN
1286 if (numBoundingSet == 0) {
1287 // owner of max bitrate request has timed out
1288 // empty bounding set has been sent
1289 return 0;
1290 }
1291 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001292 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001293 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001294 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1295 if (_cbRtcpBandwidthObserver) {
1296 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001297 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001298 }
1299 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001300}
1301
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001302void RTCPReceiver::RegisterRtcpStatisticsCallback(
1303 RtcpStatisticsCallback* callback) {
1304 CriticalSectionScoped cs(_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001305 stats_callback_ = callback;
1306}
1307
1308RtcpStatisticsCallback* RTCPReceiver::GetRtcpStatisticsCallback() {
1309 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1310 return stats_callback_;
1311}
1312
niklase@google.com470e71d2011-07-07 08:21:25 +00001313// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001314void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001315 RTCPPacketInformation& rtcpPacketInformation) {
1316 // Process TMMBR and REMB first to avoid multiple callbacks
1317 // to OnNetworkChanged.
1318 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001319 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1320 UpdateTMMBR();
1321 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001322 unsigned int local_ssrc = 0;
1323 {
1324 // We don't want to hold this critsect when triggering the callbacks below.
1325 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001326 local_ssrc = main_ssrc_;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001327 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001328 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1329 _rtpRtcp.OnRequestSendReport();
1330 }
1331 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001332 if (rtcpPacketInformation.nackSequenceNumbers.size() > 0) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001333 LOG(LS_VERBOSE) << "Incoming NACK length: "
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001334 << rtcpPacketInformation.nackSequenceNumbers.size();
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001335 _rtpRtcp.OnReceivedNACK(rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001336 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001337 }
1338 {
1339 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001340
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001341 // We need feedback that we have received a report block(s) so that we
1342 // can generate a new packet in a conference relay scenario, one received
1343 // report can generate several RTCP packets, based on number relayed/mixed
1344 // a send report block should go out to all receivers.
1345 if (_cbRtcpIntraFrameObserver) {
1346 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1347 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1348 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001349 LOG(LS_VERBOSE) << "Incoming PLI from SSRC "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001350 << rtcpPacketInformation.remoteSSRC;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001351 } else {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001352 LOG(LS_VERBOSE) << "Incoming FIR from SSRC "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001353 << rtcpPacketInformation.remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001354 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001355 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001356 }
1357 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1358 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001359 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001360 }
1361 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1362 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001363 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001364 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001365 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001366 if (_cbRtcpBandwidthObserver) {
1367 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001368 LOG(LS_VERBOSE) << "Incoming REMB: "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001369 << rtcpPacketInformation.receiverEstimatedMaxBitrate;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001370 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1371 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1372 }
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001373 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1374 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001375 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001376 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001377 rtcpPacketInformation.report_blocks,
1378 rtcpPacketInformation.rtt,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001379 now);
1380 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001381 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001382 }
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001383
1384 {
1385 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1386 if (stats_callback_) {
1387 for (ReportBlockList::const_iterator it =
1388 rtcpPacketInformation.report_blocks.begin();
1389 it != rtcpPacketInformation.report_blocks.end();
1390 ++it) {
1391 RtcpStatistics stats;
1392 stats.cumulative_lost = it->cumulativeLost;
1393 stats.extended_max_sequence_number = it->extendedHighSeqNum;
1394 stats.fraction_lost = it->fractionLost;
1395 stats.jitter = it->jitter;
1396
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001397 stats_callback_->StatisticsUpdated(stats, it->sourceSSRC);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001398 }
1399 }
1400 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001401}
1402
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001403int32_t RTCPReceiver::CNAME(uint32_t remoteSSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001404 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001405 assert(cName);
1406
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001407 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1408 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001409 if (cnameInfo == NULL) {
1410 return -1;
1411 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001412 cName[RTCP_CNAME_SIZE - 1] = 0;
1413 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1414 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001415}
1416
1417// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001418int32_t RTCPReceiver::TMMBRReceived(uint32_t size,
1419 uint32_t accNumCandidates,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001420 TMMBRSet* candidateSet) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001421 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001422
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001423 std::map<uint32_t, RTCPReceiveInformation*>::const_iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001424 receiveInfoIt = _receivedInfoMap.begin();
1425 if (receiveInfoIt == _receivedInfoMap.end()) {
1426 return -1;
1427 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001428 uint32_t num = accNumCandidates;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001429 if (candidateSet) {
1430 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1431 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1432 if (receiveInfo == NULL) {
1433 return 0;
1434 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001435 for (uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001436 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001437 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001438 _clock->TimeInMilliseconds()) == 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001439 num++;
1440 }
1441 }
1442 receiveInfoIt++;
1443 }
1444 } else {
1445 while (receiveInfoIt != _receivedInfoMap.end()) {
1446 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1447 if(receiveInfo == NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001448 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001449 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001450 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001451 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001452 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001453 }
1454 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001455}
1456
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001457} // namespace webrtc