blob: c734e0c764a3d3d59a510ba300c7241d4ebb06f0 [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
11#include "rtcp_receiver.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
13#include <string.h> //memset
14#include <cassert> //assert
15
16#include "trace.h"
17#include "critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000018#include "rtcp_utility.h"
19#include "rtp_rtcp_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000020
21namespace
22{
23 const float FRAC = 4.294967296E9;
24}
25
26namespace webrtc {
27using namespace RTCPUtility;
28using namespace RTCPHelp;
29
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000030RTCPReceiver::RTCPReceiver(const WebRtc_Word32 id, RtpRtcpClock* clock,
31 ModuleRtpRtcpImpl* owner)
32 : TMMBRHelp(),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000033 _id(id),
34 _clock(*clock),
35 _method(kRtcpOff),
36 _lastReceived(0),
37 _rtpRtcp(*owner),
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000038 _criticalSectionFeedbacks(
39 CriticalSectionWrapper::CreateCriticalSection()),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000040 _cbRtcpFeedback(NULL),
41 _cbRtcpBandwidthObserver(NULL),
42 _cbRtcpIntraFrameObserver(NULL),
43 _criticalSectionRTCPReceiver(
44 CriticalSectionWrapper::CreateCriticalSection()),
45 _SSRC(0),
46 _remoteSSRC(0),
47 _remoteSenderInfo(),
48 _lastReceivedSRNTPsecs(0),
49 _lastReceivedSRNTPfrac(0),
50 _receivedInfoMap(),
51 _packetTimeOutMS(0),
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000052 _rtt(0) {
niklase@google.com470e71d2011-07-07 08:21:25 +000053 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
54 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
55}
56
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000057RTCPReceiver::~RTCPReceiver() {
58 delete _criticalSectionRTCPReceiver;
59 delete _criticalSectionFeedbacks;
niklase@google.com470e71d2011-07-07 08:21:25 +000060
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000061 while (!_receivedReportBlockMap.empty()) {
62 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::iterator first =
63 _receivedReportBlockMap.begin();
64 delete first->second;
65 _receivedReportBlockMap.erase(first);
66 }
67 while (!_receivedInfoMap.empty()) {
68 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator first =
69 _receivedInfoMap.begin();
70 delete first->second;
71 _receivedInfoMap.erase(first);
72 }
73 while (!_receivedCnameMap.empty()) {
74 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator first =
75 _receivedCnameMap.begin();
76 delete first->second;
77 _receivedCnameMap.erase(first);
78 }
79 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id,
80 "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +000081}
82
83void
84RTCPReceiver::ChangeUniqueId(const WebRtc_Word32 id)
85{
86 _id = id;
87}
88
89RTCPMethod
90RTCPReceiver::Status() const
91{
92 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
93 return _method;
94}
95
96WebRtc_Word32
97RTCPReceiver::SetRTCPStatus(const RTCPMethod method)
98{
99 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
100 _method = method;
101 return 0;
102}
103
pwestin@webrtc.org18530052012-07-03 10:41:54 +0000104WebRtc_Word64
niklase@google.com470e71d2011-07-07 08:21:25 +0000105RTCPReceiver::LastReceived()
106{
107 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
108 return _lastReceived;
109}
110
111WebRtc_Word32
112RTCPReceiver::SetRemoteSSRC( const WebRtc_UWord32 ssrc)
113{
114 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
115
116 // new SSRC reset old reports
117 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
118 _lastReceivedSRNTPsecs = 0;
119 _lastReceivedSRNTPfrac = 0;
120
121 _remoteSSRC = ssrc;
122 return 0;
123}
124
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000125void RTCPReceiver::RegisterRtcpObservers(
126 RtcpIntraFrameObserver* intra_frame_callback,
127 RtcpBandwidthObserver* bandwidth_callback,
128 RtcpFeedback* feedback_callback) {
129 CriticalSectionScoped lock(_criticalSectionFeedbacks);
130 _cbRtcpIntraFrameObserver = intra_frame_callback;
131 _cbRtcpBandwidthObserver = bandwidth_callback;
132 _cbRtcpFeedback = feedback_callback;
niklase@google.com470e71d2011-07-07 08:21:25 +0000133}
134
niklase@google.com470e71d2011-07-07 08:21:25 +0000135
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000136void RTCPReceiver::SetSSRC(const WebRtc_UWord32 ssrc) {
137 WebRtc_UWord32 old_ssrc = 0;
138 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000139 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000140 old_ssrc = _SSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +0000141 _SSRC = ssrc;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000142 }
143 {
144 CriticalSectionScoped lock(_criticalSectionFeedbacks);
145 if (_cbRtcpIntraFrameObserver && old_ssrc != ssrc) {
146 _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, ssrc);
147 }
148 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000149}
150
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000151WebRtc_Word32 RTCPReceiver::ResetRTT(const WebRtc_UWord32 remoteSSRC) {
152 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
153 RTCPReportBlockInformation* reportBlock =
154 GetReportBlockInformation(remoteSSRC);
155 if (reportBlock == NULL) {
156 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
157 "\tfailed to GetReportBlockInformation(%u)", remoteSSRC);
158 return -1;
159 }
160 reportBlock->RTT = 0;
161 reportBlock->avgRTT = 0;
162 reportBlock->minRTT = 0;
163 reportBlock->maxRTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000164 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000165}
166
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000167WebRtc_Word32 RTCPReceiver::RTT(const WebRtc_UWord32 remoteSSRC,
168 WebRtc_UWord16* RTT,
169 WebRtc_UWord16* avgRTT,
170 WebRtc_UWord16* minRTT,
171 WebRtc_UWord16* maxRTT) const {
172 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000173
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000174 RTCPReportBlockInformation* reportBlock =
175 GetReportBlockInformation(remoteSSRC);
176
177 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000178 return -1;
179 }
180 if (RTT) {
181 *RTT = reportBlock->RTT;
182 }
183 if (avgRTT) {
184 *avgRTT = reportBlock->avgRTT;
185 }
186 if (minRTT) {
187 *minRTT = reportBlock->minRTT;
188 }
189 if (maxRTT) {
190 *maxRTT = reportBlock->maxRTT;
191 }
192 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000193}
194
mflodman@webrtc.orgd7d46882012-02-14 12:49:59 +0000195WebRtc_UWord16 RTCPReceiver::RTT() const {
196 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
197 if (!_receivedReportBlockMap.empty()) {
198 return 0;
199 }
200 return _rtt;
201}
202
203int RTCPReceiver::SetRTT(WebRtc_UWord16 rtt) {
204 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
205 if (!_receivedReportBlockMap.empty()) {
206 return -1;
207 }
208 _rtt = rtt;
209 return 0;
210}
211
niklase@google.com470e71d2011-07-07 08:21:25 +0000212WebRtc_Word32
213RTCPReceiver::NTP(WebRtc_UWord32 *ReceivedNTPsecs,
214 WebRtc_UWord32 *ReceivedNTPfrac,
215 WebRtc_UWord32 *RTCPArrivalTimeSecs,
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000216 WebRtc_UWord32 *RTCPArrivalTimeFrac,
217 WebRtc_UWord32 *rtcp_timestamp) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000218{
219 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
220 if(ReceivedNTPsecs)
221 {
222 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
223 }
224 if(ReceivedNTPfrac)
225 {
226 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
227 }
228 if(RTCPArrivalTimeFrac)
229 {
230 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
231 }
232 if(RTCPArrivalTimeSecs)
233 {
234 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
235 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000236 if (rtcp_timestamp) {
237 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
238 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000239 return 0;
240}
241
242WebRtc_Word32
243RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const
244{
245 if(senderInfo == NULL)
246 {
247 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
248 return -1;
249 }
250 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
251 if(_lastReceivedSRNTPsecs == 0)
252 {
253 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s No received SR", __FUNCTION__);
254 return -1;
255 }
256 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
257 return 0;
258}
259
260// statistics
261// we can get multiple receive reports when we receive the report from a CE
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000262WebRtc_Word32 RTCPReceiver::StatisticsReceived(
263 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000264 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000265 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
266
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000267 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::const_iterator it =
268 _receivedReportBlockMap.begin();
269
270 while (it != _receivedReportBlockMap.end()) {
271 receiveBlocks->push_back(it->second->remoteReceiveBlock);
272 it++;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000273 }
274 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000275}
276
277WebRtc_Word32
278RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
279 RTCPUtility::RTCPParserV2* rtcpParser)
280{
281 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
282
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000283 _lastReceived = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000284
285 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
286 while (pktType != RTCPUtility::kRtcpNotValidCode)
287 {
288 // Each "case" is responsible for iterate the parser to the
289 // next top level packet.
290 switch (pktType)
291 {
292 case RTCPUtility::kRtcpSrCode:
293 case RTCPUtility::kRtcpRrCode:
294 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
295 break;
296 case RTCPUtility::kRtcpSdesCode:
297 HandleSDES(*rtcpParser);
298 break;
299 case RTCPUtility::kRtcpXrVoipMetricCode:
300 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
301 break;
302 case RTCPUtility::kRtcpByeCode:
303 HandleBYE(*rtcpParser);
304 break;
305 case RTCPUtility::kRtcpRtpfbNackCode:
306 HandleNACK(*rtcpParser, rtcpPacketInformation);
307 break;
308 case RTCPUtility::kRtcpRtpfbTmmbrCode:
309 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
310 break;
311 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000312 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000313 break;
314 case RTCPUtility::kRtcpRtpfbSrReqCode:
315 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
316 break;
317 case RTCPUtility::kRtcpPsfbPliCode:
318 HandlePLI(*rtcpParser, rtcpPacketInformation);
319 break;
320 case RTCPUtility::kRtcpPsfbSliCode:
321 HandleSLI(*rtcpParser, rtcpPacketInformation);
322 break;
323 case RTCPUtility::kRtcpPsfbRpsiCode:
324 HandleRPSI(*rtcpParser, rtcpPacketInformation);
325 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000326 case RTCPUtility::kRtcpExtendedIjCode:
327 HandleIJ(*rtcpParser, rtcpPacketInformation);
328 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000329 case RTCPUtility::kRtcpPsfbFirCode:
330 HandleFIR(*rtcpParser, rtcpPacketInformation);
331 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000332 case RTCPUtility::kRtcpPsfbAppCode:
333 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
334 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000335 case RTCPUtility::kRtcpAppCode:
336 // generic application messages
337 HandleAPP(*rtcpParser, rtcpPacketInformation);
338 break;
339 case RTCPUtility::kRtcpAppItemCode:
340 // generic application messages
341 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
342 break;
343 default:
344 rtcpParser->Iterate();
345 break;
346 }
347 pktType = rtcpParser->PacketType();
348 }
349 return 0;
350}
351
352// no need for critsect we have _criticalSectionRTCPReceiver
353void
354RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
355 RTCPPacketInformation& rtcpPacketInformation)
356{
357 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
358 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
359
360 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
361
362 // SR.SenderSSRC
363 // The synchronization source identifier for the originator of this SR packet
364
365 // rtcpPacket.RR.SenderSSRC
366 // The source of the packet sender, same as of SR? or is this a CE?
367
368 const WebRtc_UWord32 remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
369 const WebRtc_UWord8 numberOfReportBlocks = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.NumberOfReportBlocks:rtcpPacket.SR.NumberOfReportBlocks;
370
371 rtcpPacketInformation.remoteSSRC = remoteSSRC;
372
373 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
374 if (!ptrReceiveInfo)
375 {
376 rtcpParser.Iterate();
377 return;
378 }
379
380 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
381 {
382 WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
383 "Received SR(%d). SSRC:0x%x, from SSRC:0x%x, to us %d.", _id, _SSRC, remoteSSRC, (_remoteSSRC == remoteSSRC)?1:0);
384
385 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
386 {
387 // only signal that we have received a SR when we accept one
388 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
389
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000390 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
391 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
392 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
393
niklase@google.com470e71d2011-07-07 08:21:25 +0000394 // We will only store the send report from one source, but
395 // we will store all the receive block
396
397 // Save the NTP time of this report
398 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
399 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
400 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
401 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
402 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
403
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000404 _clock.CurrentNTP(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000405 }
406 else
407 {
408 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
409 }
410 } else
411 {
412 WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
413 "Received RR(%d). SSRC:0x%x, from SSRC:0x%x", _id, _SSRC, remoteSSRC);
414
415 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
416 }
417 UpdateReceiveInformation(*ptrReceiveInfo);
418
419 rtcpPacketType = rtcpParser.Iterate();
420
421 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
422 {
423 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC, numberOfReportBlocks);
424 rtcpPacketType = rtcpParser.Iterate();
425 }
426}
427
428// no need for critsect we have _criticalSectionRTCPReceiver
429void
430RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
431 RTCPPacketInformation& rtcpPacketInformation,
432 const WebRtc_UWord32 remoteSSRC,
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000433 const WebRtc_UWord8 numberOfReportBlocks) {
434 // This will be called once per report block in the RTCP packet.
435 // We filter out all report blocks that are not for us.
436 // Each packet has max 31 RR blocks.
437 //
438 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000439
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000440 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
441 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000442
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000443 // Filter out all report blocks that are not for us.
444 if (rtcpPacket.ReportBlockItem.SSRC != _SSRC) {
445 // This block is not for us ignore it.
446 return;
447 }
448
449 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
450 // _criticalSectionRTCPReceiver.
451 _criticalSectionRTCPReceiver->Leave();
452 WebRtc_UWord32 sendTimeMS =
453 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
454 _criticalSectionRTCPReceiver->Enter();
455
456 RTCPReportBlockInformation* reportBlock =
457 CreateReportBlockInformation(remoteSSRC);
458 if (reportBlock == NULL) {
459 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
460 "\tfailed to CreateReportBlockInformation(%u)", remoteSSRC);
461 return;
462 }
463 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
464 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
465 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
466 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
467 reportBlock->remoteReceiveBlock.cumulativeLost =
468 rb.CumulativeNumOfPacketsLost;
469 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
470 rb.ExtendedHighestSequenceNumber;
471 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
472 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
473 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
474
475 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
476 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
477 }
478
479 WebRtc_UWord32 delaySinceLastSendReport =
480 rtcpPacket.ReportBlockItem.DelayLastSR;
481
482 // local NTP time when we received this
483 WebRtc_UWord32 lastReceivedRRNTPsecs = 0;
484 WebRtc_UWord32 lastReceivedRRNTPfrac = 0;
485
486 _clock.CurrentNTP(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
487
488 // time when we received this in MS
489 WebRtc_UWord32 receiveTimeMS = ModuleRTPUtility::ConvertNTPTimeToMS(
490 lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
491
492 // Estimate RTT
493 WebRtc_UWord32 d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
494 d /= 65536;
495 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
496
497 WebRtc_Word32 RTT = 0;
498
499 if (sendTimeMS > 0) {
500 RTT = receiveTimeMS - d - sendTimeMS;
501 if (RTT <= 0) {
502 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000503 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000504 if (RTT > reportBlock->maxRTT) {
505 // store max RTT
506 reportBlock->maxRTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000507 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000508 if (reportBlock->minRTT == 0) {
509 // first RTT
510 reportBlock->minRTT = (WebRtc_UWord16) RTT;
511 } else if (RTT < reportBlock->minRTT) {
512 // Store min RTT
513 reportBlock->minRTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000514 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000515 // store last RTT
516 reportBlock->RTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000517
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000518 // store average RTT
519 if (reportBlock->numAverageCalcs != 0) {
520 float ac = static_cast<float> (reportBlock->numAverageCalcs);
521 float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT)
522 + ((1 / (ac + 1)) * RTT);
523 reportBlock->avgRTT = static_cast<int> (newAverage + 0.5f);
524 } else {
525 // first RTT
526 reportBlock->avgRTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000527 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000528 reportBlock->numAverageCalcs++;
529 }
530
531 WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
532 " -> Received report block(%d), from SSRC:0x%x, RTT:%d, loss:%d",
533 _id, remoteSSRC, RTT, rtcpPacket.ReportBlockItem.FractionLost);
534
535 // rtcpPacketInformation
536 rtcpPacketInformation.AddReportInfo(
537 reportBlock->remoteReceiveBlock.fractionLost, (WebRtc_UWord16) RTT,
538 reportBlock->remoteReceiveBlock.extendedHighSeqNum,
539 reportBlock->remoteReceiveBlock.jitter);
niklase@google.com470e71d2011-07-07 08:21:25 +0000540}
541
542RTCPReportBlockInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000543RTCPReceiver::CreateReportBlockInformation(WebRtc_UWord32 remoteSSRC) {
544 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000545
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000546 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::iterator it =
547 _receivedReportBlockMap.find(remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000548
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000549 RTCPReportBlockInformation* ptrReportBlockInfo = NULL;
550 if (it != _receivedReportBlockMap.end()) {
551 ptrReportBlockInfo = it->second;
552 } else {
553 ptrReportBlockInfo = new RTCPReportBlockInformation;
554 _receivedReportBlockMap[remoteSSRC] = ptrReportBlockInfo;
555 }
556 return ptrReportBlockInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000557}
558
559RTCPReportBlockInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000560RTCPReceiver::GetReportBlockInformation(WebRtc_UWord32 remoteSSRC) const {
561 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000562
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000563 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::const_iterator it =
564 _receivedReportBlockMap.find(remoteSSRC);
565
566 if (it == _receivedReportBlockMap.end()) {
567 return NULL;
568 }
569 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000570}
571
572RTCPCnameInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000573RTCPReceiver::CreateCnameInformation(WebRtc_UWord32 remoteSSRC) {
574 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000575
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000576 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator it =
577 _receivedCnameMap.find(remoteSSRC);
578
579 if (it != _receivedCnameMap.end()) {
580 return it->second;
581 }
582 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000583 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000584 _receivedCnameMap[remoteSSRC] = cnameInfo;
585 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000586}
587
588RTCPCnameInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000589RTCPReceiver::GetCnameInformation(WebRtc_UWord32 remoteSSRC) const {
590 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000591
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000592 std::map<WebRtc_UWord32, RTCPCnameInformation*>::const_iterator it =
593 _receivedCnameMap.find(remoteSSRC);
594
595 if (it == _receivedCnameMap.end()) {
596 return NULL;
597 }
598 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000599}
600
601RTCPReceiveInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000602RTCPReceiver::CreateReceiveInformation(WebRtc_UWord32 remoteSSRC) {
603 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000604
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000605 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator it =
606 _receivedInfoMap.find(remoteSSRC);
607
608 if (it != _receivedInfoMap.end()) {
609 return it->second;
610 }
611 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
612 _receivedInfoMap[remoteSSRC] = receiveInfo;
613 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000614}
615
616RTCPReceiveInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000617RTCPReceiver::GetReceiveInformation(WebRtc_UWord32 remoteSSRC) {
618 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000619
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000620 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator it =
621 _receivedInfoMap.find(remoteSSRC);
622 if (it == _receivedInfoMap.end()) {
623 return NULL;
624 }
625 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000626}
627
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000628void RTCPReceiver::UpdateReceiveInformation(
629 RTCPReceiveInformation& receiveInformation) {
630 // Update that this remote is alive
631 receiveInformation.lastTimeReceived = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000632}
633
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000634bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
635 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000636
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000637 bool updateBoundingSet = false;
pwestin@webrtc.org18530052012-07-03 10:41:54 +0000638 WebRtc_Word64 timeNow = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000639
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000640 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator receiveInfoIt =
641 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000642
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000643 while (receiveInfoIt != _receivedInfoMap.end()) {
644 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
645 if (receiveInfo == NULL) {
646 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000647 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000648 // time since last received rtcp packet
649 // when we dont have a lastTimeReceived and the object is marked
650 // readyForDelete it's removed from the map
651 if (receiveInfo->lastTimeReceived) {
652 /// use audio define since we don't know what interval the remote peer is
653 // using
654 if ((timeNow - receiveInfo->lastTimeReceived) >
655 5 * RTCP_INTERVAL_AUDIO_MS) {
656 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000657 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000658 // prevent that we call this over and over again
659 receiveInfo->lastTimeReceived = 0;
660 // send new TMMBN to all channels using the default codec
661 updateBoundingSet = true;
662 }
663 receiveInfoIt++;
664 } else if (receiveInfo->readyForDelete) {
665 // store our current receiveInfoItem
666 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator
667 receiveInfoItemToBeErased = receiveInfoIt;
668 receiveInfoIt++;
669 delete receiveInfoItemToBeErased->second;
670 _receivedInfoMap.erase(receiveInfoItemToBeErased);
671 } else {
672 receiveInfoIt++;
673 }
674 }
675 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000676}
677
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000678WebRtc_Word32 RTCPReceiver::BoundingSet(bool &tmmbrOwner,
hta@webrtc.org65a4e4e2012-04-30 11:23:41 +0000679 TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000680 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000681
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000682 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator receiveInfoIt =
683 _receivedInfoMap.find(_remoteSSRC);
684
685 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000686 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000687 }
688 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
689 if (receiveInfo == NULL) {
690 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
691 "%s failed to get RTCPReceiveInformation",
692 __FUNCTION__);
693 return -1;
694 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000695 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000696 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000697 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
698 for(WebRtc_UWord32 i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
699 i++) {
700 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == _SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000701 // owner of bounding set
702 tmmbrOwner = true;
703 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000704 boundingSetRec->SetEntry(i,
705 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
706 receiveInfo->TmmbnBoundingSet.PacketOH(i),
707 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000708 }
709 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000710 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000711}
712
713// no need for critsect we have _criticalSectionRTCPReceiver
714void
715RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser)
716{
717 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
718 while (pktType == RTCPUtility::kRtcpSdesChunkCode)
719 {
720 HandleSDESChunk(rtcpParser);
721 pktType = rtcpParser.Iterate();
722 }
723}
724
725// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000726void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
727 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
728 RTCPCnameInformation* cnameInfo =
729 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
730 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000731
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000732 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
733 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000734}
735
736// no need for critsect we have _criticalSectionRTCPReceiver
737void
738RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
739 RTCPPacketInformation& rtcpPacketInformation)
740{
741 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000742 if (_SSRC != rtcpPacket.NACK.MediaSSRC)
743 {
744 // Not to us.
745 rtcpParser.Iterate();
746 return;
747 }
748
749 rtcpPacketInformation.ResetNACKPacketIdArray();
750
751 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
752 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode)
753 {
754 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
755 pktType = rtcpParser.Iterate();
756 }
757}
758
759// no need for critsect we have _criticalSectionRTCPReceiver
760void
761RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
762 RTCPPacketInformation& rtcpPacketInformation)
763{
764 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
765
766 WebRtc_UWord16 bitMask = rtcpPacket.NACKItem.BitMask;
767 if(bitMask)
768 {
769 for(int i=1; i <= 16; ++i)
770 {
771 if(bitMask & 0x01)
772 {
773 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
774 }
775 bitMask = bitMask >>1;
776 }
777 }
778
779 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
780}
781
782// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000783void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
784 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000785
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000786 // clear our lists
787 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
788 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::iterator
789 reportBlockInfoIt = _receivedReportBlockMap.find(
790 rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000791
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000792 if (reportBlockInfoIt != _receivedReportBlockMap.end()) {
793 delete reportBlockInfoIt->second;
794 _receivedReportBlockMap.erase(reportBlockInfoIt);
795 }
796 // we can't delete it due to TMMBR
797 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator receiveInfoIt =
798 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000799
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000800 if (receiveInfoIt != _receivedInfoMap.end()) {
801 receiveInfoIt->second->readyForDelete = true;
802 }
803
804 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator cnameInfoIt =
805 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
806
807 if (cnameInfoIt != _receivedCnameMap.end()) {
808 delete cnameInfoIt->second;
809 _receivedCnameMap.erase(cnameInfoIt);
810 }
811 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000812}
813
814// no need for critsect we have _criticalSectionRTCPReceiver
815void
816RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
817 RTCPPacketInformation& rtcpPacketInformation)
818{
819 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
820
821 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
822
823 if(rtcpPacket.XRVOIPMetricItem.SSRC == _SSRC)
824 {
825 // Store VoIP metrics block if it's about me
826 // from OriginatorSSRC do we filter it?
827 // rtcpPacket.XR.OriginatorSSRC;
828
829 RTCPVoIPMetric receivedVoIPMetrics;
830 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
831 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
832 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
833 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
834 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
835 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
836 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
837 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
838 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
839 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
840 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
841 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
842 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
843 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
844 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
845 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
846 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
847 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
848 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
849 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
850
851 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
852
853 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
854 }
855 rtcpParser.Iterate();
856}
857
858// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000859void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
860 RTCPPacketInformation& rtcpPacketInformation) {
861 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
862 if (_SSRC == rtcpPacket.PLI.MediaSSRC) {
863 // Received a signal that we need to send a new key frame.
864 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
865 }
866 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000867}
868
869// no need for critsect we have _criticalSectionRTCPReceiver
870void
871RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
872 RTCPPacketInformation& rtcpPacketInformation)
873{
874 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
875
876 WebRtc_UWord32 senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
877 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
878 if (ptrReceiveInfo == NULL)
879 {
880 // This remote SSRC must be saved before.
881 rtcpParser.Iterate();
882 return;
883 }
884 if(rtcpPacket.TMMBR.MediaSSRC)
885 {
886 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
887 // in relay mode this is a valid number
888 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
889 }
890
891 // Use packet length to calc max number of TMMBR blocks
892 // each TMMBR block is 8 bytes
893 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
894
895 // sanity
896 if(maxNumOfTMMBRBlocks > 200) // we can't have more than what's in one packet
897 {
898 assert(false);
899 rtcpParser.Iterate();
900 return;
901 }
902 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((WebRtc_UWord32)maxNumOfTMMBRBlocks);
903
904 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
905 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode)
906 {
907 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
908 pktType = rtcpParser.Iterate();
909 }
910}
911
912// no need for critsect we have _criticalSectionRTCPReceiver
913void
914RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
915 const RTCPUtility::RTCPPacket& rtcpPacket,
916 RTCPPacketInformation& rtcpPacketInformation,
917 const WebRtc_UWord32 senderSSRC)
918{
919 if (_SSRC == rtcpPacket.TMMBRItem.SSRC &&
920 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
921 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000922 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
923 _clock.GetTimeInMS());
niklase@google.com470e71d2011-07-07 08:21:25 +0000924 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
925 }
926}
927
928// no need for critsect we have _criticalSectionRTCPReceiver
929void
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000930RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
931 RTCPPacketInformation& rtcpPacketInformation)
niklase@google.com470e71d2011-07-07 08:21:25 +0000932{
933 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
934 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.TMMBN.SenderSSRC);
935 if (ptrReceiveInfo == NULL)
936 {
937 // This remote SSRC must be saved before.
938 rtcpParser.Iterate();
939 return;
940 }
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000941 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +0000942 // Use packet length to calc max number of TMMBN blocks
943 // each TMMBN block is 8 bytes
944 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
945
946 // sanity
947 if(maxNumOfTMMBNBlocks > 200) // we cant have more than what's in one packet
948 {
949 assert(false);
950 rtcpParser.Iterate();
951 return;
952 }
953
954 ptrReceiveInfo->VerifyAndAllocateBoundingSet((WebRtc_UWord32)maxNumOfTMMBNBlocks);
955
956 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
957 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode)
958 {
959 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
960 pktType = rtcpParser.Iterate();
961 }
962}
963
964// no need for critsect we have _criticalSectionRTCPReceiver
965void
966RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
967 RTCPPacketInformation& rtcpPacketInformation)
968{
969 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
970 rtcpParser.Iterate();
971}
972
973// no need for critsect we have _criticalSectionRTCPReceiver
974void
975RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
976 const RTCPUtility::RTCPPacket& rtcpPacket)
977{
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000978 receiveInfo.TmmbnBoundingSet.AddEntry(
979 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
980 rtcpPacket.TMMBNItem.MeasuredOverhead,
981 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000982}
983
984// no need for critsect we have _criticalSectionRTCPReceiver
985void
986RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
987 RTCPPacketInformation& rtcpPacketInformation)
988{
989 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000990 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
991 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode)
992 {
993 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
994 pktType = rtcpParser.Iterate();
995 }
996}
997
998// no need for critsect we have _criticalSectionRTCPReceiver
999void
1000RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1001 RTCPPacketInformation& rtcpPacketInformation)
1002{
1003 // in theory there could be multiple slices lost
1004 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1005 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
1006}
1007
1008void
1009RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1010 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1011{
1012 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001013 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1014 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1015 {
1016 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1017 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1018 {
1019 // to us unknown
1020 // continue
1021 rtcpParser.Iterate();
1022 return;
1023 }
1024 rtcpPacketInformation.rpsiPictureId = 0;
1025
1026 // convert NativeBitString to rpsiPictureId
1027 WebRtc_UWord8 numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1028 for(WebRtc_UWord8 n = 0; n < (numberOfBytes-1); n++)
1029 {
1030 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1031 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1032 }
1033 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1034 }
1035}
1036
1037// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001038void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1039 RTCPPacketInformation& rtcpPacketInformation) {
1040 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1041 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1042 pktType = rtcpParser.Iterate();
1043 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1044 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1045 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001046 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001047 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001048}
1049
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001050// no need for critsect we have _criticalSectionRTCPReceiver
1051void
1052RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1053 RTCPPacketInformation& rtcpPacketInformation)
1054{
1055 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1056
1057 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1058 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode)
1059 {
1060 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1061 pktType = rtcpParser.Iterate();
1062 }
1063}
1064
1065void
1066RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1067 RTCPPacketInformation& rtcpPacketInformation)
1068{
1069 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1070 rtcpPacketInformation.interArrivalJitter =
1071 rtcpPacket.ExtendedJitterReportItem.Jitter;
1072}
1073
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001074void RTCPReceiver::HandleREMBItem(
1075 RTCPUtility::RTCPParserV2& rtcpParser,
1076 RTCPPacketInformation& rtcpPacketInformation) {
1077 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1078 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1079 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1080 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001081}
1082
1083// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001084void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1085 RTCPPacketInformation& rtcpPacketInformation) {
1086 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1087 RTCPReceiveInformation* ptrReceiveInfo =
1088 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001089
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001090 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1091 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1092 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1093 pktType = rtcpParser.Iterate();
1094 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001095}
1096
1097// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001098void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1099 const RTCPUtility::RTCPPacket& rtcpPacket,
1100 RTCPPacketInformation& rtcpPacketInformation) {
1101 // Is it our sender that is requested to generate a new keyframe
1102 if (_SSRC != rtcpPacket.FIRItem.SSRC) {
1103 return;
1104 }
1105 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1106 // we don't know who this originate from
1107 if (receiveInfo) {
1108 // check if we have reported this FIRSequenceNumber before
1109 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1110 receiveInfo->lastFIRSequenceNumber) {
pwestin@webrtc.org18530052012-07-03 10:41:54 +00001111 WebRtc_Word64 now = _clock.GetTimeInMS();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001112 // sanity; don't go crazy with the callbacks
1113 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1114 receiveInfo->lastFIRRequest = now;
1115 receiveInfo->lastFIRSequenceNumber =
1116 rtcpPacket.FIRItem.CommandSequenceNumber;
1117 // received signal that we need to send a new key frame
1118 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1119 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001120 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001121 } else {
1122 // received signal that we need to send a new key frame
1123 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1124 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001125}
1126
1127void
1128RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1129 RTCPPacketInformation& rtcpPacketInformation)
1130{
1131 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1132
1133 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1134 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1135 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
1136
1137 rtcpParser.Iterate();
1138}
1139
1140void
1141RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1142 RTCPPacketInformation& rtcpPacketInformation)
1143{
1144 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1145
1146 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
1147
1148 rtcpParser.Iterate();
1149}
1150
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001151WebRtc_Word32 RTCPReceiver::UpdateTMMBR() {
1152 WebRtc_Word32 numBoundingSet = 0;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001153 WebRtc_UWord32 bitrate = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001154 WebRtc_UWord32 accNumCandidates = 0;
1155
1156 WebRtc_Word32 size = TMMBRReceived(0, 0, NULL);
1157 if (size > 0) {
1158 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1159 // Get candidate set from receiver.
1160 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1161 } else {
1162 // Candidate set empty.
1163 VerifyAndAllocateCandidateSet(0); // resets candidate set
1164 }
1165 // Find bounding set
1166 TMMBRSet* boundingSet = NULL;
1167 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1168 if (numBoundingSet == -1) {
1169 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1170 "Failed to find TMMBR bounding set.");
1171 return -1;
1172 }
1173 // Set bounding set
1174 // Inform remote clients about the new bandwidth
1175 // inform the remote client
1176 _rtpRtcp.SetTMMBN(boundingSet);
1177
1178 // might trigger a TMMBN
1179 if (numBoundingSet == 0) {
1180 // owner of max bitrate request has timed out
1181 // empty bounding set has been sent
1182 return 0;
1183 }
1184 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001185 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001186 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001187 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1188 if (_cbRtcpBandwidthObserver) {
1189 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
1190 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id,
1191 "Set TMMBR request:%d kbps", bitrate);
1192 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001193 }
1194 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001195}
1196
1197// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001198void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001199 RTCPPacketInformation& rtcpPacketInformation) {
1200 // Process TMMBR and REMB first to avoid multiple callbacks
1201 // to OnNetworkChanged.
1202 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
1203 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1204 "SIG [RTCP] Incoming TMMBR to id:%d", _id);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001205
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001206 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1207 UpdateTMMBR();
1208 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001209 unsigned int local_ssrc = 0;
1210 {
1211 // We don't want to hold this critsect when triggering the callbacks below.
1212 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1213 local_ssrc = _SSRC;
1214 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001215 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1216 _rtpRtcp.OnRequestSendReport();
1217 }
1218 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
1219 if (rtcpPacketInformation.nackSequenceNumbersLength > 0) {
1220 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1221 "SIG [RTCP] Incoming NACK length:%d",
1222 rtcpPacketInformation.nackSequenceNumbersLength);
1223 _rtpRtcp.OnReceivedNACK(
1224 rtcpPacketInformation.nackSequenceNumbersLength,
1225 rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001226 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001227 }
1228 {
1229 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001230
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001231 // We need feedback that we have received a report block(s) so that we
1232 // can generate a new packet in a conference relay scenario, one received
1233 // report can generate several RTCP packets, based on number relayed/mixed
1234 // a send report block should go out to all receivers.
1235 if (_cbRtcpIntraFrameObserver) {
1236 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1237 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1238 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
1239 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1240 "SIG [RTCP] Incoming PLI from SSRC:0x%x",
1241 rtcpPacketInformation.remoteSSRC);
1242 } else {
1243 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1244 "SIG [RTCP] Incoming FIR from SSRC:0x%x",
1245 rtcpPacketInformation.remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001246 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001247 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001248 }
1249 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1250 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001251 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001252 }
1253 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1254 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001255 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001256 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001257 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001258 if (_cbRtcpBandwidthObserver) {
1259 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
1260 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1261 "SIG [RTCP] Incoming REMB:%d",
1262 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1263 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1264 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1265 }
1266 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1267 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) &&
1268 rtcpPacketInformation.reportBlock) {
pwestin@webrtc.org18530052012-07-03 10:41:54 +00001269 WebRtc_Word64 now = _clock.GetTimeInMS();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001270 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
1271 rtcpPacketInformation.remoteSSRC,
1272 rtcpPacketInformation.fractionLost,
1273 rtcpPacketInformation.roundTripTime,
1274 rtcpPacketInformation.lastReceivedExtendedHighSeqNum,
1275 now);
1276 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001277 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001278 if(_cbRtcpFeedback) {
1279 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr) {
1280 _cbRtcpFeedback->OnSendReportReceived(_id,
stefan@webrtc.org976a7e62012-09-21 13:20:21 +00001281 rtcpPacketInformation.remoteSSRC,
1282 rtcpPacketInformation.ntp_secs,
1283 rtcpPacketInformation.ntp_frac,
1284 rtcpPacketInformation.rtp_timestamp);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001285 } else {
1286 _cbRtcpFeedback->OnReceiveReportReceived(_id,
1287 rtcpPacketInformation.remoteSSRC);
1288 }
1289 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpXrVoipMetric) {
1290 _cbRtcpFeedback->OnXRVoIPMetricReceived(_id,
1291 rtcpPacketInformation.VoIPMetric);
1292 }
1293 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpApp) {
1294 _cbRtcpFeedback->OnApplicationDataReceived(_id,
1295 rtcpPacketInformation.applicationSubType,
1296 rtcpPacketInformation.applicationName,
1297 rtcpPacketInformation.applicationLength,
1298 rtcpPacketInformation.applicationData);
1299 }
1300 }
1301 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001302}
1303
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001304WebRtc_Word32 RTCPReceiver::CNAME(const WebRtc_UWord32 remoteSSRC,
1305 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001306 assert(cName);
1307
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001308 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1309 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001310 if (cnameInfo == NULL) {
1311 return -1;
1312 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001313 cName[RTCP_CNAME_SIZE - 1] = 0;
1314 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1315 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001316}
1317
1318// no callbacks allowed inside this function
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001319WebRtc_Word32 RTCPReceiver::TMMBRReceived(const WebRtc_UWord32 size,
1320 const WebRtc_UWord32 accNumCandidates,
1321 TMMBRSet* candidateSet) const {
1322 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001323
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001324 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::const_iterator
1325 receiveInfoIt = _receivedInfoMap.begin();
1326 if (receiveInfoIt == _receivedInfoMap.end()) {
1327 return -1;
1328 }
1329 WebRtc_UWord32 num = accNumCandidates;
1330 if (candidateSet) {
1331 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1332 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1333 if (receiveInfo == NULL) {
1334 return 0;
1335 }
1336 for (WebRtc_UWord32 i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001337 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001338 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
1339 _clock.GetTimeInMS()) == 0) {
1340 num++;
1341 }
1342 }
1343 receiveInfoIt++;
1344 }
1345 } else {
1346 while (receiveInfoIt != _receivedInfoMap.end()) {
1347 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1348 if(receiveInfo == NULL) {
1349 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
1350 "%s failed to get RTCPReceiveInformation",
1351 __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +00001352 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001353 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001354 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001355 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001356 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001357 }
1358 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001359}
1360
1361WebRtc_Word32
1362RTCPReceiver::SetPacketTimeout(const WebRtc_UWord32 timeoutMS)
1363{
1364 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1365 _packetTimeOutMS = timeoutMS;
1366 return 0;
1367}
1368
1369void RTCPReceiver::PacketTimeout()
1370{
1371 if(_packetTimeOutMS == 0)
1372 {
1373 // not configured
1374 return;
1375 }
1376
1377 bool packetTimeOut = false;
1378 {
1379 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1380 if(_lastReceived == 0)
1381 {
1382 // not active
1383 return;
1384 }
1385
pwestin@webrtc.org18530052012-07-03 10:41:54 +00001386 WebRtc_Word64 now = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +00001387 if(now - _lastReceived > _packetTimeOutMS)
1388 {
1389 packetTimeOut = true;
1390 _lastReceived = 0; // only one callback
1391 }
1392 }
1393 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1394 if(packetTimeOut && _cbRtcpFeedback)
1395 {
1396 _cbRtcpFeedback->OnRTCPPacketTimeout(_id);
1397 }
1398}
1399} // namespace webrtc