blob: a95fddede25b255c836242de2d550bb491db0f14 [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"
21#include "webrtc/system_wrappers/interface/trace.h"
22#include "webrtc/system_wrappers/interface/trace_event.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000023
niklase@google.com470e71d2011-07-07 08:21:25 +000024namespace webrtc {
25using namespace RTCPUtility;
26using namespace RTCPHelp;
27
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000028// The number of RTCP time intervals needed to trigger a timeout.
29const int kRrTimeoutIntervals = 3;
30
pbos@webrtc.org2f446732013-04-08 11:08:41 +000031RTCPReceiver::RTCPReceiver(const int32_t id, Clock* clock,
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000032 ModuleRtpRtcpImpl* owner)
33 : TMMBRHelp(),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000034 _id(id),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000035 _clock(clock),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000036 _method(kRtcpOff),
37 _lastReceived(0),
38 _rtpRtcp(*owner),
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000039 _criticalSectionFeedbacks(
40 CriticalSectionWrapper::CreateCriticalSection()),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000041 _cbRtcpFeedback(NULL),
42 _cbRtcpBandwidthObserver(NULL),
43 _cbRtcpIntraFrameObserver(NULL),
44 _criticalSectionRTCPReceiver(
45 CriticalSectionWrapper::CreateCriticalSection()),
stefan@webrtc.org28a331e2013-09-17 07:49:56 +000046 main_ssrc_(0),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000047 _remoteSSRC(0),
48 _remoteSenderInfo(),
49 _lastReceivedSRNTPsecs(0),
50 _lastReceivedSRNTPfrac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000051 _lastReceivedXRNTPsecs(0),
52 _lastReceivedXRNTPfrac(0),
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +000053 xr_rr_rtt_ms_(0),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000054 _receivedInfoMap(),
55 _packetTimeOutMS(0),
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000056 _lastReceivedRrMs(0),
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +000057 _lastIncreasedSequenceNumberMs(0),
58 stats_callback_(NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +000059 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
60 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
61}
62
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000063RTCPReceiver::~RTCPReceiver() {
64 delete _criticalSectionRTCPReceiver;
65 delete _criticalSectionFeedbacks;
niklase@google.com470e71d2011-07-07 08:21:25 +000066
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000067 while (!_receivedReportBlockMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000068 std::map<uint32_t, RTCPReportBlockInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000069 _receivedReportBlockMap.begin();
70 delete first->second;
71 _receivedReportBlockMap.erase(first);
72 }
73 while (!_receivedInfoMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000074 std::map<uint32_t, RTCPReceiveInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000075 _receivedInfoMap.begin();
76 delete first->second;
77 _receivedInfoMap.erase(first);
78 }
79 while (!_receivedCnameMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000080 std::map<uint32_t, RTCPCnameInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000081 _receivedCnameMap.begin();
82 delete first->second;
83 _receivedCnameMap.erase(first);
84 }
85 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id,
86 "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +000087}
88
89void
pbos@webrtc.org2f446732013-04-08 11:08:41 +000090RTCPReceiver::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +000091{
92 _id = id;
93}
94
95RTCPMethod
96RTCPReceiver::Status() const
97{
98 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
99 return _method;
100}
101
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000102int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000103RTCPReceiver::SetRTCPStatus(const RTCPMethod method)
104{
105 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
106 _method = method;
107 return 0;
108}
109
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000110int64_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000111RTCPReceiver::LastReceived()
112{
113 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
114 return _lastReceived;
115}
116
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000117int64_t
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000118RTCPReceiver::LastReceivedReceiverReport() const {
119 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000120 int64_t last_received_rr = -1;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000121 for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin();
122 it != _receivedInfoMap.end(); ++it) {
123 if (it->second->lastTimeReceived > last_received_rr) {
124 last_received_rr = it->second->lastTimeReceived;
125 }
126 }
127 return last_received_rr;
128}
129
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000130int32_t
131RTCPReceiver::SetRemoteSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000132{
133 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
134
135 // new SSRC reset old reports
136 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
137 _lastReceivedSRNTPsecs = 0;
138 _lastReceivedSRNTPfrac = 0;
139
140 _remoteSSRC = ssrc;
141 return 0;
142}
143
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000144uint32_t RTCPReceiver::RemoteSSRC() const {
145 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
146 return _remoteSSRC;
147}
148
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000149void RTCPReceiver::RegisterRtcpObservers(
150 RtcpIntraFrameObserver* intra_frame_callback,
151 RtcpBandwidthObserver* bandwidth_callback,
152 RtcpFeedback* feedback_callback) {
153 CriticalSectionScoped lock(_criticalSectionFeedbacks);
154 _cbRtcpIntraFrameObserver = intra_frame_callback;
155 _cbRtcpBandwidthObserver = bandwidth_callback;
156 _cbRtcpFeedback = feedback_callback;
niklase@google.com470e71d2011-07-07 08:21:25 +0000157}
158
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000159void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
160 const std::set<uint32_t>& registered_ssrcs) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000161 uint32_t old_ssrc = 0;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000162 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000163 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000164 old_ssrc = main_ssrc_;
165 main_ssrc_ = main_ssrc;
166 registered_ssrcs_ = registered_ssrcs;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000167 }
168 {
169 CriticalSectionScoped lock(_criticalSectionFeedbacks);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000170 if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) {
171 _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc);
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000172 }
173 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000174}
175
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000176int32_t RTCPReceiver::ResetRTT(const uint32_t remoteSSRC) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000177 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
178 RTCPReportBlockInformation* reportBlock =
179 GetReportBlockInformation(remoteSSRC);
180 if (reportBlock == NULL) {
181 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
182 "\tfailed to GetReportBlockInformation(%u)", remoteSSRC);
183 return -1;
184 }
185 reportBlock->RTT = 0;
186 reportBlock->avgRTT = 0;
187 reportBlock->minRTT = 0;
188 reportBlock->maxRTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000189 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000190}
191
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000192int32_t RTCPReceiver::RTT(uint32_t remoteSSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000193 uint16_t* RTT,
194 uint16_t* avgRTT,
195 uint16_t* minRTT,
196 uint16_t* maxRTT) const {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000197 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000198
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000199 RTCPReportBlockInformation* reportBlock =
200 GetReportBlockInformation(remoteSSRC);
201
202 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000203 return -1;
204 }
205 if (RTT) {
206 *RTT = reportBlock->RTT;
207 }
208 if (avgRTT) {
209 *avgRTT = reportBlock->avgRTT;
210 }
211 if (minRTT) {
212 *minRTT = reportBlock->minRTT;
213 }
214 if (maxRTT) {
215 *maxRTT = reportBlock->maxRTT;
216 }
217 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000218}
219
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000220bool RTCPReceiver::GetAndResetXrRrRtt(uint16_t* rtt_ms) {
221 assert(rtt_ms);
222 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
223 if (xr_rr_rtt_ms_ == 0) {
224 return false;
225 }
226 *rtt_ms = xr_rr_rtt_ms_;
227 xr_rr_rtt_ms_ = 0;
228 return true;
229}
230
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000231int32_t
232RTCPReceiver::NTP(uint32_t *ReceivedNTPsecs,
233 uint32_t *ReceivedNTPfrac,
234 uint32_t *RTCPArrivalTimeSecs,
235 uint32_t *RTCPArrivalTimeFrac,
236 uint32_t *rtcp_timestamp) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000237{
238 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
239 if(ReceivedNTPsecs)
240 {
241 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
242 }
243 if(ReceivedNTPfrac)
244 {
245 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
246 }
247 if(RTCPArrivalTimeFrac)
248 {
249 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
250 }
251 if(RTCPArrivalTimeSecs)
252 {
253 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
254 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000255 if (rtcp_timestamp) {
256 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
257 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000258 return 0;
259}
260
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000261bool RTCPReceiver::LastReceivedXrReferenceTimeInfo(
262 RtcpReceiveTimeInfo* info) const {
263 assert(info);
264 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
265 if (_lastReceivedXRNTPsecs == 0 && _lastReceivedXRNTPfrac == 0) {
266 return false;
267 }
268
269 info->sourceSSRC = _remoteXRReceiveTimeInfo.sourceSSRC;
270 info->lastRR = _remoteXRReceiveTimeInfo.lastRR;
271
272 // Get the delay since last received report (RFC 3611).
273 uint32_t receive_time = RTCPUtility::MidNtp(_lastReceivedXRNTPsecs,
274 _lastReceivedXRNTPfrac);
275
276 uint32_t ntp_sec = 0;
277 uint32_t ntp_frac = 0;
278 _clock->CurrentNtp(ntp_sec, ntp_frac);
279 uint32_t now = RTCPUtility::MidNtp(ntp_sec, ntp_frac);
280
281 info->delaySinceLastRR = now - receive_time;
282 return true;
283}
284
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000285int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000286RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const
287{
288 if(senderInfo == NULL)
289 {
290 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
291 return -1;
292 }
293 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
294 if(_lastReceivedSRNTPsecs == 0)
295 {
296 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s No received SR", __FUNCTION__);
297 return -1;
298 }
299 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
300 return 0;
301}
302
303// statistics
304// we can get multiple receive reports when we receive the report from a CE
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000305int32_t RTCPReceiver::StatisticsReceived(
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000306 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000307 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000308 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
309
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000310 std::map<uint32_t, RTCPReportBlockInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000311 _receivedReportBlockMap.begin();
312
313 while (it != _receivedReportBlockMap.end()) {
314 receiveBlocks->push_back(it->second->remoteReceiveBlock);
315 it++;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000316 }
317 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000318}
319
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000320int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000321RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
322 RTCPUtility::RTCPParserV2* rtcpParser)
323{
324 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
325
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000326 _lastReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000327
328 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
329 while (pktType != RTCPUtility::kRtcpNotValidCode)
330 {
331 // Each "case" is responsible for iterate the parser to the
332 // next top level packet.
333 switch (pktType)
334 {
335 case RTCPUtility::kRtcpSrCode:
336 case RTCPUtility::kRtcpRrCode:
337 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
338 break;
339 case RTCPUtility::kRtcpSdesCode:
340 HandleSDES(*rtcpParser);
341 break;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000342 case RTCPUtility::kRtcpXrHeaderCode:
343 HandleXrHeader(*rtcpParser, rtcpPacketInformation);
344 break;
345 case RTCPUtility::kRtcpXrReceiverReferenceTimeCode:
346 HandleXrReceiveReferenceTime(*rtcpParser, rtcpPacketInformation);
347 break;
348 case RTCPUtility::kRtcpXrDlrrReportBlockCode:
349 HandleXrDlrrReportBlock(*rtcpParser, rtcpPacketInformation);
350 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000351 case RTCPUtility::kRtcpXrVoipMetricCode:
352 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
353 break;
354 case RTCPUtility::kRtcpByeCode:
355 HandleBYE(*rtcpParser);
356 break;
357 case RTCPUtility::kRtcpRtpfbNackCode:
358 HandleNACK(*rtcpParser, rtcpPacketInformation);
359 break;
360 case RTCPUtility::kRtcpRtpfbTmmbrCode:
361 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
362 break;
363 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000364 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000365 break;
366 case RTCPUtility::kRtcpRtpfbSrReqCode:
367 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
368 break;
369 case RTCPUtility::kRtcpPsfbPliCode:
370 HandlePLI(*rtcpParser, rtcpPacketInformation);
371 break;
372 case RTCPUtility::kRtcpPsfbSliCode:
373 HandleSLI(*rtcpParser, rtcpPacketInformation);
374 break;
375 case RTCPUtility::kRtcpPsfbRpsiCode:
376 HandleRPSI(*rtcpParser, rtcpPacketInformation);
377 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000378 case RTCPUtility::kRtcpExtendedIjCode:
379 HandleIJ(*rtcpParser, rtcpPacketInformation);
380 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000381 case RTCPUtility::kRtcpPsfbFirCode:
382 HandleFIR(*rtcpParser, rtcpPacketInformation);
383 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000384 case RTCPUtility::kRtcpPsfbAppCode:
385 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
386 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000387 case RTCPUtility::kRtcpAppCode:
388 // generic application messages
389 HandleAPP(*rtcpParser, rtcpPacketInformation);
390 break;
391 case RTCPUtility::kRtcpAppItemCode:
392 // generic application messages
393 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
394 break;
395 default:
396 rtcpParser->Iterate();
397 break;
398 }
399 pktType = rtcpParser->PacketType();
400 }
401 return 0;
402}
403
404// no need for critsect we have _criticalSectionRTCPReceiver
405void
406RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
407 RTCPPacketInformation& rtcpPacketInformation)
408{
409 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
410 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
411
412 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
413
414 // SR.SenderSSRC
415 // The synchronization source identifier for the originator of this SR packet
416
417 // rtcpPacket.RR.SenderSSRC
418 // The source of the packet sender, same as of SR? or is this a CE?
419
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000420 const uint32_t remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
421 const uint8_t numberOfReportBlocks = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.NumberOfReportBlocks:rtcpPacket.SR.NumberOfReportBlocks;
niklase@google.com470e71d2011-07-07 08:21:25 +0000422
423 rtcpPacketInformation.remoteSSRC = remoteSSRC;
424
425 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
426 if (!ptrReceiveInfo)
427 {
428 rtcpParser.Iterate();
429 return;
430 }
431
432 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
433 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000434 TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
435 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000436 "ssrc", main_ssrc_);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000437
niklase@google.com470e71d2011-07-07 08:21:25 +0000438 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
439 {
440 // only signal that we have received a SR when we accept one
441 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
442
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000443 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
444 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
445 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
446
niklase@google.com470e71d2011-07-07 08:21:25 +0000447 // We will only store the send report from one source, but
448 // we will store all the receive block
449
450 // Save the NTP time of this report
451 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
452 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
453 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
454 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
455 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
456
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000457 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000458 }
459 else
460 {
461 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
462 }
463 } else
464 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000465 TRACE_EVENT_INSTANT2("webrtc_rtp", "RR",
466 "remote_ssrc", remoteSSRC,
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000467 "ssrc", main_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000468
469 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
470 }
471 UpdateReceiveInformation(*ptrReceiveInfo);
472
473 rtcpPacketType = rtcpParser.Iterate();
474
475 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
476 {
477 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC, numberOfReportBlocks);
478 rtcpPacketType = rtcpParser.Iterate();
479 }
480}
481
482// no need for critsect we have _criticalSectionRTCPReceiver
483void
484RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
485 RTCPPacketInformation& rtcpPacketInformation,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000486 const uint32_t remoteSSRC,
487 const uint8_t numberOfReportBlocks) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000488 // This will be called once per report block in the RTCP packet.
489 // We filter out all report blocks that are not for us.
490 // Each packet has max 31 RR blocks.
491 //
492 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000493
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000494 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
495 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000496
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000497 // Filter out all report blocks that are not for us.
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000498 if (registered_ssrcs_.find(rtcpPacket.ReportBlockItem.SSRC) ==
499 registered_ssrcs_.end()) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000500 // This block is not for us ignore it.
501 return;
502 }
503
504 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
505 // _criticalSectionRTCPReceiver.
506 _criticalSectionRTCPReceiver->Leave();
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000507 uint32_t sendTimeMS =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000508 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
509 _criticalSectionRTCPReceiver->Enter();
510
511 RTCPReportBlockInformation* reportBlock =
512 CreateReportBlockInformation(remoteSSRC);
513 if (reportBlock == NULL) {
514 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
515 "\tfailed to CreateReportBlockInformation(%u)", remoteSSRC);
516 return;
517 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000518
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000519 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000520 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
521 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
522 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
523 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
524 reportBlock->remoteReceiveBlock.cumulativeLost =
525 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000526 if (rb.ExtendedHighestSequenceNumber >
527 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
528 // We have successfully delivered new RTP packets to the remote side after
529 // the last RR was sent from the remote side.
530 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000531 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000532 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
533 rb.ExtendedHighestSequenceNumber;
534 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
535 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
536 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
537
538 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
539 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
540 }
541
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000542 uint32_t delaySinceLastSendReport =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000543 rtcpPacket.ReportBlockItem.DelayLastSR;
544
545 // local NTP time when we received this
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000546 uint32_t lastReceivedRRNTPsecs = 0;
547 uint32_t lastReceivedRRNTPfrac = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000548
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000549 _clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000550
551 // time when we received this in MS
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000552 uint32_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
553 lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000554
555 // Estimate RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000556 uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000557 d /= 65536;
558 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
559
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000560 int32_t RTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000561
562 if (sendTimeMS > 0) {
563 RTT = receiveTimeMS - d - sendTimeMS;
564 if (RTT <= 0) {
565 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000566 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000567 if (RTT > reportBlock->maxRTT) {
568 // store max RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000569 reportBlock->maxRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000570 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000571 if (reportBlock->minRTT == 0) {
572 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000573 reportBlock->minRTT = (uint16_t) RTT;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000574 } else if (RTT < reportBlock->minRTT) {
575 // Store min RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000576 reportBlock->minRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000577 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000578 // store last RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000579 reportBlock->RTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000580
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000581 // store average RTT
582 if (reportBlock->numAverageCalcs != 0) {
583 float ac = static_cast<float> (reportBlock->numAverageCalcs);
584 float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT)
585 + ((1 / (ac + 1)) * RTT);
586 reportBlock->avgRTT = static_cast<int> (newAverage + 0.5f);
587 } else {
588 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000589 reportBlock->avgRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000590 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000591 reportBlock->numAverageCalcs++;
592 }
593
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000594 TRACE_COUNTER_ID1("webrtc_rtp", "RR_RTT", rb.SSRC, RTT);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000595
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000596 rtcpPacketInformation.AddReportInfo(*reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000597}
598
599RTCPReportBlockInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000600RTCPReceiver::CreateReportBlockInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000601 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000602
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000603 std::map<uint32_t, RTCPReportBlockInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000604 _receivedReportBlockMap.find(remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000605
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000606 RTCPReportBlockInformation* ptrReportBlockInfo = NULL;
607 if (it != _receivedReportBlockMap.end()) {
608 ptrReportBlockInfo = it->second;
609 } else {
610 ptrReportBlockInfo = new RTCPReportBlockInformation;
611 _receivedReportBlockMap[remoteSSRC] = ptrReportBlockInfo;
612 }
613 return ptrReportBlockInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000614}
615
616RTCPReportBlockInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000617RTCPReceiver::GetReportBlockInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000618 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000619
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000620 std::map<uint32_t, RTCPReportBlockInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000621 _receivedReportBlockMap.find(remoteSSRC);
622
623 if (it == _receivedReportBlockMap.end()) {
624 return NULL;
625 }
626 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000627}
628
629RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000630RTCPReceiver::CreateCnameInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000631 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000632
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000633 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000634 _receivedCnameMap.find(remoteSSRC);
635
636 if (it != _receivedCnameMap.end()) {
637 return it->second;
638 }
639 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000640 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000641 _receivedCnameMap[remoteSSRC] = cnameInfo;
642 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000643}
644
645RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000646RTCPReceiver::GetCnameInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000647 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000648
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000649 std::map<uint32_t, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000650 _receivedCnameMap.find(remoteSSRC);
651
652 if (it == _receivedCnameMap.end()) {
653 return NULL;
654 }
655 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000656}
657
658RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000659RTCPReceiver::CreateReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000660 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000661
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000662 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000663 _receivedInfoMap.find(remoteSSRC);
664
665 if (it != _receivedInfoMap.end()) {
666 return it->second;
667 }
668 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
669 _receivedInfoMap[remoteSSRC] = receiveInfo;
670 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000671}
672
673RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000674RTCPReceiver::GetReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000675 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000676
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000677 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000678 _receivedInfoMap.find(remoteSSRC);
679 if (it == _receivedInfoMap.end()) {
680 return NULL;
681 }
682 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000683}
684
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000685void RTCPReceiver::UpdateReceiveInformation(
686 RTCPReceiveInformation& receiveInformation) {
687 // Update that this remote is alive
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000688 receiveInformation.lastTimeReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000689}
690
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000691bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
692 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
693 if (_lastReceivedRrMs == 0)
694 return false;
695
696 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000697 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000698 // Reset the timer to only trigger one log.
699 _lastReceivedRrMs = 0;
700 return true;
701 }
702 return false;
703}
704
705bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
706 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
707 if (_lastIncreasedSequenceNumberMs == 0)
708 return false;
709
710 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000711 if (_clock->TimeInMilliseconds() > _lastIncreasedSequenceNumberMs +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000712 time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000713 // Reset the timer to only trigger one log.
714 _lastIncreasedSequenceNumberMs = 0;
715 return true;
716 }
717 return false;
718}
719
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000720bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
721 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000722
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000723 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000724 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000725
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000726 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000727 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000728
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000729 while (receiveInfoIt != _receivedInfoMap.end()) {
730 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
731 if (receiveInfo == NULL) {
732 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000733 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000734 // time since last received rtcp packet
735 // when we dont have a lastTimeReceived and the object is marked
736 // readyForDelete it's removed from the map
737 if (receiveInfo->lastTimeReceived) {
738 /// use audio define since we don't know what interval the remote peer is
739 // using
740 if ((timeNow - receiveInfo->lastTimeReceived) >
741 5 * RTCP_INTERVAL_AUDIO_MS) {
742 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000743 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000744 // prevent that we call this over and over again
745 receiveInfo->lastTimeReceived = 0;
746 // send new TMMBN to all channels using the default codec
747 updateBoundingSet = true;
748 }
749 receiveInfoIt++;
750 } else if (receiveInfo->readyForDelete) {
751 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000752 std::map<uint32_t, RTCPReceiveInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000753 receiveInfoItemToBeErased = receiveInfoIt;
754 receiveInfoIt++;
755 delete receiveInfoItemToBeErased->second;
756 _receivedInfoMap.erase(receiveInfoItemToBeErased);
757 } else {
758 receiveInfoIt++;
759 }
760 }
761 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000762}
763
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000764int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000765 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000766
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000767 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000768 _receivedInfoMap.find(_remoteSSRC);
769
770 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000771 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000772 }
773 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
774 if (receiveInfo == NULL) {
775 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
776 "%s failed to get RTCPReceiveInformation",
777 __FUNCTION__);
778 return -1;
779 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000780 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000781 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000782 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000783 for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000784 i++) {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000785 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000786 // owner of bounding set
787 tmmbrOwner = true;
788 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000789 boundingSetRec->SetEntry(i,
790 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
791 receiveInfo->TmmbnBoundingSet.PacketOH(i),
792 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000793 }
794 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000795 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000796}
797
798// no need for critsect we have _criticalSectionRTCPReceiver
799void
800RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser)
801{
802 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
803 while (pktType == RTCPUtility::kRtcpSdesChunkCode)
804 {
805 HandleSDESChunk(rtcpParser);
806 pktType = rtcpParser.Iterate();
807 }
808}
809
810// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000811void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
812 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
813 RTCPCnameInformation* cnameInfo =
814 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
815 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000816
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000817 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
818 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000819}
820
821// no need for critsect we have _criticalSectionRTCPReceiver
822void
823RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
824 RTCPPacketInformation& rtcpPacketInformation)
825{
826 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000827 if (main_ssrc_ != rtcpPacket.NACK.MediaSSRC)
niklase@google.com470e71d2011-07-07 08:21:25 +0000828 {
829 // Not to us.
830 rtcpParser.Iterate();
831 return;
832 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000833 rtcpPacketInformation.ResetNACKPacketIdArray();
834
835 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
836 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode)
837 {
838 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
839 pktType = rtcpParser.Iterate();
840 }
841}
842
843// no need for critsect we have _criticalSectionRTCPReceiver
844void
845RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
846 RTCPPacketInformation& rtcpPacketInformation)
847{
848 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
849
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000850 uint16_t bitMask = rtcpPacket.NACKItem.BitMask;
niklase@google.com470e71d2011-07-07 08:21:25 +0000851 if(bitMask)
852 {
853 for(int i=1; i <= 16; ++i)
854 {
855 if(bitMask & 0x01)
856 {
857 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
858 }
859 bitMask = bitMask >>1;
860 }
861 }
862
863 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
864}
865
866// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000867void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
868 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000869
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000870 // clear our lists
871 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000872 std::map<uint32_t, RTCPReportBlockInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000873 reportBlockInfoIt = _receivedReportBlockMap.find(
874 rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000875
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000876 if (reportBlockInfoIt != _receivedReportBlockMap.end()) {
877 delete reportBlockInfoIt->second;
878 _receivedReportBlockMap.erase(reportBlockInfoIt);
879 }
880 // we can't delete it due to TMMBR
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000881 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000882 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000883
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000884 if (receiveInfoIt != _receivedInfoMap.end()) {
885 receiveInfoIt->second->readyForDelete = true;
886 }
887
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000888 std::map<uint32_t, RTCPCnameInformation*>::iterator cnameInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000889 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
890
891 if (cnameInfoIt != _receivedCnameMap.end()) {
892 delete cnameInfoIt->second;
893 _receivedCnameMap.erase(cnameInfoIt);
894 }
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000895 xr_rr_rtt_ms_ = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000896 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000897}
898
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000899void RTCPReceiver::HandleXrHeader(
900 RTCPUtility::RTCPParserV2& parser,
901 RTCPPacketInformation& rtcpPacketInformation) {
902 const RTCPUtility::RTCPPacket& packet = parser.Packet();
903
904 rtcpPacketInformation.xr_originator_ssrc = packet.XR.OriginatorSSRC;
905
906 parser.Iterate();
907}
908
909void RTCPReceiver::HandleXrReceiveReferenceTime(
910 RTCPUtility::RTCPParserV2& parser,
911 RTCPPacketInformation& rtcpPacketInformation) {
912 const RTCPUtility::RTCPPacket& packet = parser.Packet();
913
914 _remoteXRReceiveTimeInfo.sourceSSRC =
915 rtcpPacketInformation.xr_originator_ssrc;
916
917 _remoteXRReceiveTimeInfo.lastRR = RTCPUtility::MidNtp(
918 packet.XRReceiverReferenceTimeItem.NTPMostSignificant,
919 packet.XRReceiverReferenceTimeItem.NTPLeastSignificant);
920
921 _clock->CurrentNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);
922
923 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
924
925 parser.Iterate();
926}
927
928void RTCPReceiver::HandleXrDlrrReportBlock(
929 RTCPUtility::RTCPParserV2& parser,
930 RTCPPacketInformation& rtcpPacketInformation) {
931 const RTCPUtility::RTCPPacket& packet = parser.Packet();
932 // Iterate through sub-block(s), if any.
933 RTCPUtility::RTCPPacketTypes packet_type = parser.Iterate();
934
935 while (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
936 HandleXrDlrrReportBlockItem(packet, rtcpPacketInformation);
937 packet_type = parser.Iterate();
938 }
939}
940
941void RTCPReceiver::HandleXrDlrrReportBlockItem(
942 const RTCPUtility::RTCPPacket& packet,
943 RTCPPacketInformation& rtcpPacketInformation) {
944 if (registered_ssrcs_.find(packet.XRDLRRReportBlockItem.SSRC) ==
945 registered_ssrcs_.end()) {
946 // Not to us.
947 return;
948 }
949
950 rtcpPacketInformation.xr_dlrr_item = true;
951
952 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
953 // _criticalSectionRTCPReceiver.
954 _criticalSectionRTCPReceiver->Leave();
955
956 int64_t send_time_ms;
957 bool found = _rtpRtcp.SendTimeOfXrRrReport(
958 packet.XRDLRRReportBlockItem.LastRR, &send_time_ms);
959
960 _criticalSectionRTCPReceiver->Enter();
961
962 if (!found) {
963 return;
964 }
965
966 // The DelayLastRR field is in units of 1/65536 sec.
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000967 uint32_t delay_rr_ms =
968 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0x0000ffff) * 1000) >> 16) +
969 (((packet.XRDLRRReportBlockItem.DelayLastRR & 0xffff0000) >> 16) * 1000);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000970
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000971 int32_t rtt = _clock->CurrentNtpInMilliseconds() - delay_rr_ms - send_time_ms;
972
973 xr_rr_rtt_ms_ = static_cast<uint16_t>(std::max(rtt, 1));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000974
975 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
976}
977
niklase@google.com470e71d2011-07-07 08:21:25 +0000978// no need for critsect we have _criticalSectionRTCPReceiver
979void
980RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
981 RTCPPacketInformation& rtcpPacketInformation)
982{
983 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
984
985 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
986
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000987 if(rtcpPacket.XRVOIPMetricItem.SSRC == main_ssrc_)
niklase@google.com470e71d2011-07-07 08:21:25 +0000988 {
989 // Store VoIP metrics block if it's about me
990 // from OriginatorSSRC do we filter it?
991 // rtcpPacket.XR.OriginatorSSRC;
992
993 RTCPVoIPMetric receivedVoIPMetrics;
994 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
995 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
996 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
997 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
998 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
999 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
1000 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
1001 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
1002 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
1003 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
1004 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
1005 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
1006 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
1007 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
1008 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
1009 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
1010 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
1011 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
1012 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
1013 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
1014
1015 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
1016
1017 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
1018 }
1019 rtcpParser.Iterate();
1020}
1021
1022// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001023void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
1024 RTCPPacketInformation& rtcpPacketInformation) {
1025 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001026 if (main_ssrc_ == rtcpPacket.PLI.MediaSSRC) {
justinlin@chromium.org7bfb3a32013-05-13 22:59:00 +00001027 TRACE_EVENT_INSTANT0("webrtc_rtp", "PLI");
1028
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001029 // Received a signal that we need to send a new key frame.
1030 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
1031 }
1032 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +00001033}
1034
1035// no need for critsect we have _criticalSectionRTCPReceiver
1036void
1037RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
1038 RTCPPacketInformation& rtcpPacketInformation)
1039{
1040 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1041
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001042 uint32_t senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001043 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
1044 if (ptrReceiveInfo == NULL)
1045 {
1046 // This remote SSRC must be saved before.
1047 rtcpParser.Iterate();
1048 return;
1049 }
1050 if(rtcpPacket.TMMBR.MediaSSRC)
1051 {
1052 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
1053 // in relay mode this is a valid number
1054 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
1055 }
1056
1057 // Use packet length to calc max number of TMMBR blocks
1058 // each TMMBR block is 8 bytes
1059 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
1060
1061 // sanity
1062 if(maxNumOfTMMBRBlocks > 200) // we can't have more than what's in one packet
1063 {
1064 assert(false);
1065 rtcpParser.Iterate();
1066 return;
1067 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001068 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((uint32_t)maxNumOfTMMBRBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001069
1070 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1071 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode)
1072 {
1073 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
1074 pktType = rtcpParser.Iterate();
1075 }
1076}
1077
1078// no need for critsect we have _criticalSectionRTCPReceiver
1079void
1080RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
1081 const RTCPUtility::RTCPPacket& rtcpPacket,
1082 RTCPPacketInformation& rtcpPacketInformation,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001083 const uint32_t senderSSRC)
niklase@google.com470e71d2011-07-07 08:21:25 +00001084{
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001085 if (main_ssrc_ == rtcpPacket.TMMBRItem.SSRC &&
niklase@google.com470e71d2011-07-07 08:21:25 +00001086 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
1087 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001088 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001089 _clock->TimeInMilliseconds());
niklase@google.com470e71d2011-07-07 08:21:25 +00001090 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
1091 }
1092}
1093
1094// no need for critsect we have _criticalSectionRTCPReceiver
1095void
hta@webrtc.org9d54cd12012-04-30 08:24:55 +00001096RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
1097 RTCPPacketInformation& rtcpPacketInformation)
niklase@google.com470e71d2011-07-07 08:21:25 +00001098{
1099 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1100 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.TMMBN.SenderSSRC);
1101 if (ptrReceiveInfo == NULL)
1102 {
1103 // This remote SSRC must be saved before.
1104 rtcpParser.Iterate();
1105 return;
1106 }
hta@webrtc.org9d54cd12012-04-30 08:24:55 +00001107 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +00001108 // Use packet length to calc max number of TMMBN blocks
1109 // each TMMBN block is 8 bytes
1110 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
1111
1112 // sanity
1113 if(maxNumOfTMMBNBlocks > 200) // we cant have more than what's in one packet
1114 {
1115 assert(false);
1116 rtcpParser.Iterate();
1117 return;
1118 }
1119
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001120 ptrReceiveInfo->VerifyAndAllocateBoundingSet((uint32_t)maxNumOfTMMBNBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001121
1122 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1123 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode)
1124 {
1125 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
1126 pktType = rtcpParser.Iterate();
1127 }
1128}
1129
1130// no need for critsect we have _criticalSectionRTCPReceiver
1131void
1132RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
1133 RTCPPacketInformation& rtcpPacketInformation)
1134{
1135 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
1136 rtcpParser.Iterate();
1137}
1138
1139// no need for critsect we have _criticalSectionRTCPReceiver
1140void
1141RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
1142 const RTCPUtility::RTCPPacket& rtcpPacket)
1143{
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001144 receiveInfo.TmmbnBoundingSet.AddEntry(
1145 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
1146 rtcpPacket.TMMBNItem.MeasuredOverhead,
1147 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001148}
1149
1150// no need for critsect we have _criticalSectionRTCPReceiver
1151void
1152RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
1153 RTCPPacketInformation& rtcpPacketInformation)
1154{
1155 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001156 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1157 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode)
1158 {
1159 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1160 pktType = rtcpParser.Iterate();
1161 }
1162}
1163
1164// no need for critsect we have _criticalSectionRTCPReceiver
1165void
1166RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1167 RTCPPacketInformation& rtcpPacketInformation)
1168{
1169 // in theory there could be multiple slices lost
1170 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1171 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
1172}
1173
1174void
1175RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1176 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1177{
1178 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001179 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1180 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1181 {
1182 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1183 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1184 {
1185 // to us unknown
1186 // continue
1187 rtcpParser.Iterate();
1188 return;
1189 }
1190 rtcpPacketInformation.rpsiPictureId = 0;
1191
1192 // convert NativeBitString to rpsiPictureId
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001193 uint8_t numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1194 for(uint8_t n = 0; n < (numberOfBytes-1); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001195 {
1196 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1197 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1198 }
1199 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1200 }
1201}
1202
1203// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001204void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1205 RTCPPacketInformation& rtcpPacketInformation) {
1206 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1207 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1208 pktType = rtcpParser.Iterate();
1209 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1210 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1211 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001212 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001213 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001214}
1215
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001216// no need for critsect we have _criticalSectionRTCPReceiver
1217void
1218RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1219 RTCPPacketInformation& rtcpPacketInformation)
1220{
1221 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1222
1223 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1224 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode)
1225 {
1226 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1227 pktType = rtcpParser.Iterate();
1228 }
1229}
1230
1231void
1232RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1233 RTCPPacketInformation& rtcpPacketInformation)
1234{
1235 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1236 rtcpPacketInformation.interArrivalJitter =
1237 rtcpPacket.ExtendedJitterReportItem.Jitter;
1238}
1239
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001240void RTCPReceiver::HandleREMBItem(
1241 RTCPUtility::RTCPParserV2& rtcpParser,
1242 RTCPPacketInformation& rtcpPacketInformation) {
1243 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1244 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1245 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1246 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001247}
1248
1249// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001250void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1251 RTCPPacketInformation& rtcpPacketInformation) {
1252 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1253 RTCPReceiveInformation* ptrReceiveInfo =
1254 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001255
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001256 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1257 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1258 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1259 pktType = rtcpParser.Iterate();
1260 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001261}
1262
1263// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001264void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1265 const RTCPUtility::RTCPPacket& rtcpPacket,
1266 RTCPPacketInformation& rtcpPacketInformation) {
1267 // Is it our sender that is requested to generate a new keyframe
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001268 if (main_ssrc_ != rtcpPacket.FIRItem.SSRC) {
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001269 return;
1270 }
1271 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1272 // we don't know who this originate from
1273 if (receiveInfo) {
1274 // check if we have reported this FIRSequenceNumber before
1275 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1276 receiveInfo->lastFIRSequenceNumber) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001277 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001278 // sanity; don't go crazy with the callbacks
1279 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1280 receiveInfo->lastFIRRequest = now;
1281 receiveInfo->lastFIRSequenceNumber =
1282 rtcpPacket.FIRItem.CommandSequenceNumber;
1283 // received signal that we need to send a new key frame
1284 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1285 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001286 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001287 } else {
1288 // received signal that we need to send a new key frame
1289 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1290 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001291}
1292
1293void
1294RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1295 RTCPPacketInformation& rtcpPacketInformation)
1296{
1297 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1298
1299 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1300 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1301 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
1302
1303 rtcpParser.Iterate();
1304}
1305
1306void
1307RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1308 RTCPPacketInformation& rtcpPacketInformation)
1309{
1310 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1311
1312 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
1313
1314 rtcpParser.Iterate();
1315}
1316
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001317int32_t RTCPReceiver::UpdateTMMBR() {
1318 int32_t numBoundingSet = 0;
1319 uint32_t bitrate = 0;
1320 uint32_t accNumCandidates = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001321
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001322 int32_t size = TMMBRReceived(0, 0, NULL);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001323 if (size > 0) {
1324 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1325 // Get candidate set from receiver.
1326 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1327 } else {
1328 // Candidate set empty.
1329 VerifyAndAllocateCandidateSet(0); // resets candidate set
1330 }
1331 // Find bounding set
1332 TMMBRSet* boundingSet = NULL;
1333 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1334 if (numBoundingSet == -1) {
1335 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1336 "Failed to find TMMBR bounding set.");
1337 return -1;
1338 }
1339 // Set bounding set
1340 // Inform remote clients about the new bandwidth
1341 // inform the remote client
1342 _rtpRtcp.SetTMMBN(boundingSet);
1343
1344 // might trigger a TMMBN
1345 if (numBoundingSet == 0) {
1346 // owner of max bitrate request has timed out
1347 // empty bounding set has been sent
1348 return 0;
1349 }
1350 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001351 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001352 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001353 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1354 if (_cbRtcpBandwidthObserver) {
1355 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
1356 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id,
1357 "Set TMMBR request:%d kbps", bitrate);
1358 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001359 }
1360 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001361}
1362
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001363void RTCPReceiver::RegisterRtcpStatisticsCallback(
1364 RtcpStatisticsCallback* callback) {
1365 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1366 if (callback != NULL)
1367 assert(stats_callback_ == NULL);
1368 stats_callback_ = callback;
1369}
1370
1371RtcpStatisticsCallback* RTCPReceiver::GetRtcpStatisticsCallback() {
1372 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1373 return stats_callback_;
1374}
1375
niklase@google.com470e71d2011-07-07 08:21:25 +00001376// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001377void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001378 RTCPPacketInformation& rtcpPacketInformation) {
1379 // Process TMMBR and REMB first to avoid multiple callbacks
1380 // to OnNetworkChanged.
1381 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
1382 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1383 "SIG [RTCP] Incoming TMMBR to id:%d", _id);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001384
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001385 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1386 UpdateTMMBR();
1387 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001388 unsigned int local_ssrc = 0;
1389 {
1390 // We don't want to hold this critsect when triggering the callbacks below.
1391 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001392 local_ssrc = main_ssrc_;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001393 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001394 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1395 _rtpRtcp.OnRequestSendReport();
1396 }
1397 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001398 if (rtcpPacketInformation.nackSequenceNumbers.size() > 0) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001399 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1400 "SIG [RTCP] Incoming NACK length:%d",
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001401 rtcpPacketInformation.nackSequenceNumbers.size());
1402 _rtpRtcp.OnReceivedNACK(rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001403 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001404 }
1405 {
1406 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001407
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001408 // We need feedback that we have received a report block(s) so that we
1409 // can generate a new packet in a conference relay scenario, one received
1410 // report can generate several RTCP packets, based on number relayed/mixed
1411 // a send report block should go out to all receivers.
1412 if (_cbRtcpIntraFrameObserver) {
1413 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1414 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1415 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
1416 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1417 "SIG [RTCP] Incoming PLI from SSRC:0x%x",
1418 rtcpPacketInformation.remoteSSRC);
1419 } else {
1420 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1421 "SIG [RTCP] Incoming FIR from SSRC:0x%x",
1422 rtcpPacketInformation.remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001423 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001424 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001425 }
1426 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1427 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001428 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001429 }
1430 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1431 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001432 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001433 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001434 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001435 if (_cbRtcpBandwidthObserver) {
1436 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
1437 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1438 "SIG [RTCP] Incoming REMB:%d",
1439 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1440 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1441 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1442 }
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001443 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1444 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001445 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001446 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001447 rtcpPacketInformation.report_blocks,
1448 rtcpPacketInformation.rtt,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001449 now);
1450 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001451 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001452 if(_cbRtcpFeedback) {
solenberg@webrtc.org91811e22013-06-25 20:36:14 +00001453 if(!(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr)) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001454 _cbRtcpFeedback->OnReceiveReportReceived(_id,
1455 rtcpPacketInformation.remoteSSRC);
1456 }
1457 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpXrVoipMetric) {
1458 _cbRtcpFeedback->OnXRVoIPMetricReceived(_id,
1459 rtcpPacketInformation.VoIPMetric);
1460 }
1461 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpApp) {
1462 _cbRtcpFeedback->OnApplicationDataReceived(_id,
1463 rtcpPacketInformation.applicationSubType,
1464 rtcpPacketInformation.applicationName,
1465 rtcpPacketInformation.applicationLength,
1466 rtcpPacketInformation.applicationData);
1467 }
1468 }
1469 }
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001470
1471 {
1472 CriticalSectionScoped cs(_criticalSectionFeedbacks);
1473 if (stats_callback_) {
1474 for (ReportBlockList::const_iterator it =
1475 rtcpPacketInformation.report_blocks.begin();
1476 it != rtcpPacketInformation.report_blocks.end();
1477 ++it) {
1478 RtcpStatistics stats;
1479 stats.cumulative_lost = it->cumulativeLost;
1480 stats.extended_max_sequence_number = it->extendedHighSeqNum;
1481 stats.fraction_lost = it->fractionLost;
1482 stats.jitter = it->jitter;
1483
1484 stats_callback_->StatisticsUpdated(stats, local_ssrc);
1485 }
1486 }
1487 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001488}
1489
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001490int32_t RTCPReceiver::CNAME(const uint32_t remoteSSRC,
1491 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001492 assert(cName);
1493
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001494 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1495 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001496 if (cnameInfo == NULL) {
1497 return -1;
1498 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001499 cName[RTCP_CNAME_SIZE - 1] = 0;
1500 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1501 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001502}
1503
1504// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001505int32_t RTCPReceiver::TMMBRReceived(const uint32_t size,
1506 const uint32_t accNumCandidates,
1507 TMMBRSet* candidateSet) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001508 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001509
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001510 std::map<uint32_t, RTCPReceiveInformation*>::const_iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001511 receiveInfoIt = _receivedInfoMap.begin();
1512 if (receiveInfoIt == _receivedInfoMap.end()) {
1513 return -1;
1514 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001515 uint32_t num = accNumCandidates;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001516 if (candidateSet) {
1517 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1518 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1519 if (receiveInfo == NULL) {
1520 return 0;
1521 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001522 for (uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001523 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001524 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001525 _clock->TimeInMilliseconds()) == 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001526 num++;
1527 }
1528 }
1529 receiveInfoIt++;
1530 }
1531 } else {
1532 while (receiveInfoIt != _receivedInfoMap.end()) {
1533 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1534 if(receiveInfo == NULL) {
1535 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
1536 "%s failed to get RTCPReceiveInformation",
1537 __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +00001538 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001539 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001540 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001541 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001542 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001543 }
1544 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001545}
1546
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001547} // namespace webrtc