blob: f4c23a21eb6de9414959a81904c54b258f5678bb [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
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000030// The number of RTCP time intervals needed to trigger a timeout.
31const int kRrTimeoutIntervals = 3;
32
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000033RTCPReceiver::RTCPReceiver(const WebRtc_Word32 id, RtpRtcpClock* clock,
34 ModuleRtpRtcpImpl* owner)
35 : TMMBRHelp(),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000036 _id(id),
37 _clock(*clock),
38 _method(kRtcpOff),
39 _lastReceived(0),
40 _rtpRtcp(*owner),
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000041 _criticalSectionFeedbacks(
42 CriticalSectionWrapper::CreateCriticalSection()),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000043 _cbRtcpFeedback(NULL),
44 _cbRtcpBandwidthObserver(NULL),
45 _cbRtcpIntraFrameObserver(NULL),
46 _criticalSectionRTCPReceiver(
47 CriticalSectionWrapper::CreateCriticalSection()),
48 _SSRC(0),
49 _remoteSSRC(0),
50 _remoteSenderInfo(),
51 _lastReceivedSRNTPsecs(0),
52 _lastReceivedSRNTPfrac(0),
53 _receivedInfoMap(),
54 _packetTimeOutMS(0),
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000055 _lastReceivedRrMs(0),
56 _lastIncreasedSequenceNumberMs(0),
57 _rtt(0) {
niklase@google.com470e71d2011-07-07 08:21:25 +000058 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
59 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
60}
61
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000062RTCPReceiver::~RTCPReceiver() {
63 delete _criticalSectionRTCPReceiver;
64 delete _criticalSectionFeedbacks;
niklase@google.com470e71d2011-07-07 08:21:25 +000065
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000066 while (!_receivedReportBlockMap.empty()) {
67 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::iterator first =
68 _receivedReportBlockMap.begin();
69 delete first->second;
70 _receivedReportBlockMap.erase(first);
71 }
72 while (!_receivedInfoMap.empty()) {
73 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator first =
74 _receivedInfoMap.begin();
75 delete first->second;
76 _receivedInfoMap.erase(first);
77 }
78 while (!_receivedCnameMap.empty()) {
79 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator first =
80 _receivedCnameMap.begin();
81 delete first->second;
82 _receivedCnameMap.erase(first);
83 }
84 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id,
85 "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +000086}
87
88void
89RTCPReceiver::ChangeUniqueId(const WebRtc_Word32 id)
90{
91 _id = id;
92}
93
94RTCPMethod
95RTCPReceiver::Status() const
96{
97 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
98 return _method;
99}
100
101WebRtc_Word32
102RTCPReceiver::SetRTCPStatus(const RTCPMethod method)
103{
104 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
105 _method = method;
106 return 0;
107}
108
pwestin@webrtc.org18530052012-07-03 10:41:54 +0000109WebRtc_Word64
niklase@google.com470e71d2011-07-07 08:21:25 +0000110RTCPReceiver::LastReceived()
111{
112 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
113 return _lastReceived;
114}
115
116WebRtc_Word32
117RTCPReceiver::SetRemoteSSRC( const WebRtc_UWord32 ssrc)
118{
119 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
120
121 // new SSRC reset old reports
122 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
123 _lastReceivedSRNTPsecs = 0;
124 _lastReceivedSRNTPfrac = 0;
125
126 _remoteSSRC = ssrc;
127 return 0;
128}
129
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000130void RTCPReceiver::RegisterRtcpObservers(
131 RtcpIntraFrameObserver* intra_frame_callback,
132 RtcpBandwidthObserver* bandwidth_callback,
133 RtcpFeedback* feedback_callback) {
134 CriticalSectionScoped lock(_criticalSectionFeedbacks);
135 _cbRtcpIntraFrameObserver = intra_frame_callback;
136 _cbRtcpBandwidthObserver = bandwidth_callback;
137 _cbRtcpFeedback = feedback_callback;
niklase@google.com470e71d2011-07-07 08:21:25 +0000138}
139
niklase@google.com470e71d2011-07-07 08:21:25 +0000140
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000141void RTCPReceiver::SetSSRC(const WebRtc_UWord32 ssrc) {
142 WebRtc_UWord32 old_ssrc = 0;
143 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000144 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000145 old_ssrc = _SSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +0000146 _SSRC = ssrc;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000147 }
148 {
149 CriticalSectionScoped lock(_criticalSectionFeedbacks);
150 if (_cbRtcpIntraFrameObserver && old_ssrc != ssrc) {
151 _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, ssrc);
152 }
153 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000154}
155
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000156WebRtc_Word32 RTCPReceiver::ResetRTT(const WebRtc_UWord32 remoteSSRC) {
157 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
158 RTCPReportBlockInformation* reportBlock =
159 GetReportBlockInformation(remoteSSRC);
160 if (reportBlock == NULL) {
161 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
162 "\tfailed to GetReportBlockInformation(%u)", remoteSSRC);
163 return -1;
164 }
165 reportBlock->RTT = 0;
166 reportBlock->avgRTT = 0;
167 reportBlock->minRTT = 0;
168 reportBlock->maxRTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000169 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000170}
171
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000172WebRtc_Word32 RTCPReceiver::RTT(const WebRtc_UWord32 remoteSSRC,
173 WebRtc_UWord16* RTT,
174 WebRtc_UWord16* avgRTT,
175 WebRtc_UWord16* minRTT,
176 WebRtc_UWord16* maxRTT) const {
177 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000178
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000179 RTCPReportBlockInformation* reportBlock =
180 GetReportBlockInformation(remoteSSRC);
181
182 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000183 return -1;
184 }
185 if (RTT) {
186 *RTT = reportBlock->RTT;
187 }
188 if (avgRTT) {
189 *avgRTT = reportBlock->avgRTT;
190 }
191 if (minRTT) {
192 *minRTT = reportBlock->minRTT;
193 }
194 if (maxRTT) {
195 *maxRTT = reportBlock->maxRTT;
196 }
197 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000198}
199
mflodman@webrtc.orgd7d46882012-02-14 12:49:59 +0000200WebRtc_UWord16 RTCPReceiver::RTT() const {
201 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
202 if (!_receivedReportBlockMap.empty()) {
203 return 0;
204 }
205 return _rtt;
206}
207
208int RTCPReceiver::SetRTT(WebRtc_UWord16 rtt) {
209 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
210 if (!_receivedReportBlockMap.empty()) {
211 return -1;
212 }
213 _rtt = rtt;
214 return 0;
215}
216
niklase@google.com470e71d2011-07-07 08:21:25 +0000217WebRtc_Word32
218RTCPReceiver::NTP(WebRtc_UWord32 *ReceivedNTPsecs,
219 WebRtc_UWord32 *ReceivedNTPfrac,
220 WebRtc_UWord32 *RTCPArrivalTimeSecs,
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000221 WebRtc_UWord32 *RTCPArrivalTimeFrac,
222 WebRtc_UWord32 *rtcp_timestamp) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000223{
224 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
225 if(ReceivedNTPsecs)
226 {
227 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
228 }
229 if(ReceivedNTPfrac)
230 {
231 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
232 }
233 if(RTCPArrivalTimeFrac)
234 {
235 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
236 }
237 if(RTCPArrivalTimeSecs)
238 {
239 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
240 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000241 if (rtcp_timestamp) {
242 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
243 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000244 return 0;
245}
246
247WebRtc_Word32
248RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const
249{
250 if(senderInfo == NULL)
251 {
252 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
253 return -1;
254 }
255 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
256 if(_lastReceivedSRNTPsecs == 0)
257 {
258 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s No received SR", __FUNCTION__);
259 return -1;
260 }
261 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
262 return 0;
263}
264
265// statistics
266// we can get multiple receive reports when we receive the report from a CE
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000267WebRtc_Word32 RTCPReceiver::StatisticsReceived(
268 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000269 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000270 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
271
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000272 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::const_iterator it =
273 _receivedReportBlockMap.begin();
274
275 while (it != _receivedReportBlockMap.end()) {
276 receiveBlocks->push_back(it->second->remoteReceiveBlock);
277 it++;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000278 }
279 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000280}
281
282WebRtc_Word32
283RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
284 RTCPUtility::RTCPParserV2* rtcpParser)
285{
286 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
287
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000288 _lastReceived = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000289
290 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
291 while (pktType != RTCPUtility::kRtcpNotValidCode)
292 {
293 // Each "case" is responsible for iterate the parser to the
294 // next top level packet.
295 switch (pktType)
296 {
297 case RTCPUtility::kRtcpSrCode:
298 case RTCPUtility::kRtcpRrCode:
299 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
300 break;
301 case RTCPUtility::kRtcpSdesCode:
302 HandleSDES(*rtcpParser);
303 break;
304 case RTCPUtility::kRtcpXrVoipMetricCode:
305 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
306 break;
307 case RTCPUtility::kRtcpByeCode:
308 HandleBYE(*rtcpParser);
309 break;
310 case RTCPUtility::kRtcpRtpfbNackCode:
311 HandleNACK(*rtcpParser, rtcpPacketInformation);
312 break;
313 case RTCPUtility::kRtcpRtpfbTmmbrCode:
314 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
315 break;
316 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000317 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000318 break;
319 case RTCPUtility::kRtcpRtpfbSrReqCode:
320 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
321 break;
322 case RTCPUtility::kRtcpPsfbPliCode:
323 HandlePLI(*rtcpParser, rtcpPacketInformation);
324 break;
325 case RTCPUtility::kRtcpPsfbSliCode:
326 HandleSLI(*rtcpParser, rtcpPacketInformation);
327 break;
328 case RTCPUtility::kRtcpPsfbRpsiCode:
329 HandleRPSI(*rtcpParser, rtcpPacketInformation);
330 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000331 case RTCPUtility::kRtcpExtendedIjCode:
332 HandleIJ(*rtcpParser, rtcpPacketInformation);
333 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000334 case RTCPUtility::kRtcpPsfbFirCode:
335 HandleFIR(*rtcpParser, rtcpPacketInformation);
336 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000337 case RTCPUtility::kRtcpPsfbAppCode:
338 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
339 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000340 case RTCPUtility::kRtcpAppCode:
341 // generic application messages
342 HandleAPP(*rtcpParser, rtcpPacketInformation);
343 break;
344 case RTCPUtility::kRtcpAppItemCode:
345 // generic application messages
346 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
347 break;
348 default:
349 rtcpParser->Iterate();
350 break;
351 }
352 pktType = rtcpParser->PacketType();
353 }
354 return 0;
355}
356
357// no need for critsect we have _criticalSectionRTCPReceiver
358void
359RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
360 RTCPPacketInformation& rtcpPacketInformation)
361{
362 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
363 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
364
365 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
366
367 // SR.SenderSSRC
368 // The synchronization source identifier for the originator of this SR packet
369
370 // rtcpPacket.RR.SenderSSRC
371 // The source of the packet sender, same as of SR? or is this a CE?
372
373 const WebRtc_UWord32 remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
374 const WebRtc_UWord8 numberOfReportBlocks = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.NumberOfReportBlocks:rtcpPacket.SR.NumberOfReportBlocks;
375
376 rtcpPacketInformation.remoteSSRC = remoteSSRC;
377
378 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
379 if (!ptrReceiveInfo)
380 {
381 rtcpParser.Iterate();
382 return;
383 }
384
385 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
386 {
387 WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
388 "Received SR(%d). SSRC:0x%x, from SSRC:0x%x, to us %d.", _id, _SSRC, remoteSSRC, (_remoteSSRC == remoteSSRC)?1:0);
389
390 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
391 {
392 // only signal that we have received a SR when we accept one
393 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
394
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000395 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
396 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
397 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
398
niklase@google.com470e71d2011-07-07 08:21:25 +0000399 // We will only store the send report from one source, but
400 // we will store all the receive block
401
402 // Save the NTP time of this report
403 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
404 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
405 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
406 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
407 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
408
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000409 _clock.CurrentNTP(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000410 }
411 else
412 {
413 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
414 }
415 } else
416 {
417 WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
418 "Received RR(%d). SSRC:0x%x, from SSRC:0x%x", _id, _SSRC, remoteSSRC);
419
420 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
421 }
422 UpdateReceiveInformation(*ptrReceiveInfo);
423
424 rtcpPacketType = rtcpParser.Iterate();
425
426 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
427 {
428 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC, numberOfReportBlocks);
429 rtcpPacketType = rtcpParser.Iterate();
430 }
431}
432
433// no need for critsect we have _criticalSectionRTCPReceiver
434void
435RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
436 RTCPPacketInformation& rtcpPacketInformation,
437 const WebRtc_UWord32 remoteSSRC,
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000438 const WebRtc_UWord8 numberOfReportBlocks) {
439 // This will be called once per report block in the RTCP packet.
440 // We filter out all report blocks that are not for us.
441 // Each packet has max 31 RR blocks.
442 //
443 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000444
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000445 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
446 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000447
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000448 // Filter out all report blocks that are not for us.
449 if (rtcpPacket.ReportBlockItem.SSRC != _SSRC) {
450 // This block is not for us ignore it.
451 return;
452 }
453
454 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
455 // _criticalSectionRTCPReceiver.
456 _criticalSectionRTCPReceiver->Leave();
457 WebRtc_UWord32 sendTimeMS =
458 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
459 _criticalSectionRTCPReceiver->Enter();
460
461 RTCPReportBlockInformation* reportBlock =
462 CreateReportBlockInformation(remoteSSRC);
463 if (reportBlock == NULL) {
464 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
465 "\tfailed to CreateReportBlockInformation(%u)", remoteSSRC);
466 return;
467 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000468
469 _lastReceivedRrMs = _clock.GetTimeInMS();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000470 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
471 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
472 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
473 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
474 reportBlock->remoteReceiveBlock.cumulativeLost =
475 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000476 if (rb.ExtendedHighestSequenceNumber >
477 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
478 // We have successfully delivered new RTP packets to the remote side after
479 // the last RR was sent from the remote side.
480 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000481 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000482 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
483 rb.ExtendedHighestSequenceNumber;
484 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
485 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
486 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
487
488 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
489 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
490 }
491
492 WebRtc_UWord32 delaySinceLastSendReport =
493 rtcpPacket.ReportBlockItem.DelayLastSR;
494
495 // local NTP time when we received this
496 WebRtc_UWord32 lastReceivedRRNTPsecs = 0;
497 WebRtc_UWord32 lastReceivedRRNTPfrac = 0;
498
499 _clock.CurrentNTP(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
500
501 // time when we received this in MS
502 WebRtc_UWord32 receiveTimeMS = ModuleRTPUtility::ConvertNTPTimeToMS(
503 lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
504
505 // Estimate RTT
506 WebRtc_UWord32 d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
507 d /= 65536;
508 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
509
510 WebRtc_Word32 RTT = 0;
511
512 if (sendTimeMS > 0) {
513 RTT = receiveTimeMS - d - sendTimeMS;
514 if (RTT <= 0) {
515 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000516 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000517 if (RTT > reportBlock->maxRTT) {
518 // store max RTT
519 reportBlock->maxRTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000520 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000521 if (reportBlock->minRTT == 0) {
522 // first RTT
523 reportBlock->minRTT = (WebRtc_UWord16) RTT;
524 } else if (RTT < reportBlock->minRTT) {
525 // Store min RTT
526 reportBlock->minRTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000527 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000528 // store last RTT
529 reportBlock->RTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000530
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000531 // store average RTT
532 if (reportBlock->numAverageCalcs != 0) {
533 float ac = static_cast<float> (reportBlock->numAverageCalcs);
534 float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT)
535 + ((1 / (ac + 1)) * RTT);
536 reportBlock->avgRTT = static_cast<int> (newAverage + 0.5f);
537 } else {
538 // first RTT
539 reportBlock->avgRTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000540 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000541 reportBlock->numAverageCalcs++;
542 }
543
544 WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
545 " -> Received report block(%d), from SSRC:0x%x, RTT:%d, loss:%d",
546 _id, remoteSSRC, RTT, rtcpPacket.ReportBlockItem.FractionLost);
547
548 // rtcpPacketInformation
549 rtcpPacketInformation.AddReportInfo(
550 reportBlock->remoteReceiveBlock.fractionLost, (WebRtc_UWord16) RTT,
551 reportBlock->remoteReceiveBlock.extendedHighSeqNum,
552 reportBlock->remoteReceiveBlock.jitter);
niklase@google.com470e71d2011-07-07 08:21:25 +0000553}
554
555RTCPReportBlockInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000556RTCPReceiver::CreateReportBlockInformation(WebRtc_UWord32 remoteSSRC) {
557 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000558
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000559 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::iterator it =
560 _receivedReportBlockMap.find(remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000561
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000562 RTCPReportBlockInformation* ptrReportBlockInfo = NULL;
563 if (it != _receivedReportBlockMap.end()) {
564 ptrReportBlockInfo = it->second;
565 } else {
566 ptrReportBlockInfo = new RTCPReportBlockInformation;
567 _receivedReportBlockMap[remoteSSRC] = ptrReportBlockInfo;
568 }
569 return ptrReportBlockInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000570}
571
572RTCPReportBlockInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000573RTCPReceiver::GetReportBlockInformation(WebRtc_UWord32 remoteSSRC) const {
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, RTCPReportBlockInformation*>::const_iterator it =
577 _receivedReportBlockMap.find(remoteSSRC);
578
579 if (it == _receivedReportBlockMap.end()) {
580 return NULL;
581 }
582 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000583}
584
585RTCPCnameInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000586RTCPReceiver::CreateCnameInformation(WebRtc_UWord32 remoteSSRC) {
587 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000588
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000589 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator it =
590 _receivedCnameMap.find(remoteSSRC);
591
592 if (it != _receivedCnameMap.end()) {
593 return it->second;
594 }
595 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000596 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000597 _receivedCnameMap[remoteSSRC] = cnameInfo;
598 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000599}
600
601RTCPCnameInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000602RTCPReceiver::GetCnameInformation(WebRtc_UWord32 remoteSSRC) const {
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, RTCPCnameInformation*>::const_iterator it =
606 _receivedCnameMap.find(remoteSSRC);
607
608 if (it == _receivedCnameMap.end()) {
609 return NULL;
610 }
611 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000612}
613
614RTCPReceiveInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000615RTCPReceiver::CreateReceiveInformation(WebRtc_UWord32 remoteSSRC) {
616 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000617
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000618 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator it =
619 _receivedInfoMap.find(remoteSSRC);
620
621 if (it != _receivedInfoMap.end()) {
622 return it->second;
623 }
624 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
625 _receivedInfoMap[remoteSSRC] = receiveInfo;
626 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000627}
628
629RTCPReceiveInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000630RTCPReceiver::GetReceiveInformation(WebRtc_UWord32 remoteSSRC) {
631 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000632
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000633 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator it =
634 _receivedInfoMap.find(remoteSSRC);
635 if (it == _receivedInfoMap.end()) {
636 return NULL;
637 }
638 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000639}
640
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000641void RTCPReceiver::UpdateReceiveInformation(
642 RTCPReceiveInformation& receiveInformation) {
643 // Update that this remote is alive
644 receiveInformation.lastTimeReceived = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000645}
646
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000647bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
648 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
649 if (_lastReceivedRrMs == 0)
650 return false;
651
652 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
653 if (_clock.GetTimeInMS() > _lastReceivedRrMs + time_out_ms) {
654 // Reset the timer to only trigger one log.
655 _lastReceivedRrMs = 0;
656 return true;
657 }
658 return false;
659}
660
661bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
662 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
663 if (_lastIncreasedSequenceNumberMs == 0)
664 return false;
665
666 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
667 if (_clock.GetTimeInMS() > _lastIncreasedSequenceNumberMs + time_out_ms) {
668 // Reset the timer to only trigger one log.
669 _lastIncreasedSequenceNumberMs = 0;
670 return true;
671 }
672 return false;
673}
674
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000675bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
676 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000677
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000678 bool updateBoundingSet = false;
pwestin@webrtc.org18530052012-07-03 10:41:54 +0000679 WebRtc_Word64 timeNow = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000680
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000681 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator receiveInfoIt =
682 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000683
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000684 while (receiveInfoIt != _receivedInfoMap.end()) {
685 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
686 if (receiveInfo == NULL) {
687 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000688 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000689 // time since last received rtcp packet
690 // when we dont have a lastTimeReceived and the object is marked
691 // readyForDelete it's removed from the map
692 if (receiveInfo->lastTimeReceived) {
693 /// use audio define since we don't know what interval the remote peer is
694 // using
695 if ((timeNow - receiveInfo->lastTimeReceived) >
696 5 * RTCP_INTERVAL_AUDIO_MS) {
697 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000698 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000699 // prevent that we call this over and over again
700 receiveInfo->lastTimeReceived = 0;
701 // send new TMMBN to all channels using the default codec
702 updateBoundingSet = true;
703 }
704 receiveInfoIt++;
705 } else if (receiveInfo->readyForDelete) {
706 // store our current receiveInfoItem
707 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator
708 receiveInfoItemToBeErased = receiveInfoIt;
709 receiveInfoIt++;
710 delete receiveInfoItemToBeErased->second;
711 _receivedInfoMap.erase(receiveInfoItemToBeErased);
712 } else {
713 receiveInfoIt++;
714 }
715 }
716 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000717}
718
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000719WebRtc_Word32 RTCPReceiver::BoundingSet(bool &tmmbrOwner,
hta@webrtc.org65a4e4e2012-04-30 11:23:41 +0000720 TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000721 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000722
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000723 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator receiveInfoIt =
724 _receivedInfoMap.find(_remoteSSRC);
725
726 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000727 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000728 }
729 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
730 if (receiveInfo == NULL) {
731 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
732 "%s failed to get RTCPReceiveInformation",
733 __FUNCTION__);
734 return -1;
735 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000736 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000737 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000738 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
739 for(WebRtc_UWord32 i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
740 i++) {
741 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == _SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000742 // owner of bounding set
743 tmmbrOwner = true;
744 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000745 boundingSetRec->SetEntry(i,
746 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
747 receiveInfo->TmmbnBoundingSet.PacketOH(i),
748 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000749 }
750 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000751 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000752}
753
754// no need for critsect we have _criticalSectionRTCPReceiver
755void
756RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser)
757{
758 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
759 while (pktType == RTCPUtility::kRtcpSdesChunkCode)
760 {
761 HandleSDESChunk(rtcpParser);
762 pktType = rtcpParser.Iterate();
763 }
764}
765
766// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000767void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
768 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
769 RTCPCnameInformation* cnameInfo =
770 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
771 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000772
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000773 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
774 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000775}
776
777// no need for critsect we have _criticalSectionRTCPReceiver
778void
779RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
780 RTCPPacketInformation& rtcpPacketInformation)
781{
782 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000783 if (_SSRC != rtcpPacket.NACK.MediaSSRC)
784 {
785 // Not to us.
786 rtcpParser.Iterate();
787 return;
788 }
789
790 rtcpPacketInformation.ResetNACKPacketIdArray();
791
792 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
793 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode)
794 {
795 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
796 pktType = rtcpParser.Iterate();
797 }
798}
799
800// no need for critsect we have _criticalSectionRTCPReceiver
801void
802RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
803 RTCPPacketInformation& rtcpPacketInformation)
804{
805 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
806
807 WebRtc_UWord16 bitMask = rtcpPacket.NACKItem.BitMask;
808 if(bitMask)
809 {
810 for(int i=1; i <= 16; ++i)
811 {
812 if(bitMask & 0x01)
813 {
814 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
815 }
816 bitMask = bitMask >>1;
817 }
818 }
819
820 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
821}
822
823// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000824void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
825 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000826
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000827 // clear our lists
828 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
829 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::iterator
830 reportBlockInfoIt = _receivedReportBlockMap.find(
831 rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000832
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000833 if (reportBlockInfoIt != _receivedReportBlockMap.end()) {
834 delete reportBlockInfoIt->second;
835 _receivedReportBlockMap.erase(reportBlockInfoIt);
836 }
837 // we can't delete it due to TMMBR
838 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator receiveInfoIt =
839 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000840
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000841 if (receiveInfoIt != _receivedInfoMap.end()) {
842 receiveInfoIt->second->readyForDelete = true;
843 }
844
845 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator cnameInfoIt =
846 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
847
848 if (cnameInfoIt != _receivedCnameMap.end()) {
849 delete cnameInfoIt->second;
850 _receivedCnameMap.erase(cnameInfoIt);
851 }
852 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000853}
854
855// no need for critsect we have _criticalSectionRTCPReceiver
856void
857RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
858 RTCPPacketInformation& rtcpPacketInformation)
859{
860 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
861
862 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
863
864 if(rtcpPacket.XRVOIPMetricItem.SSRC == _SSRC)
865 {
866 // Store VoIP metrics block if it's about me
867 // from OriginatorSSRC do we filter it?
868 // rtcpPacket.XR.OriginatorSSRC;
869
870 RTCPVoIPMetric receivedVoIPMetrics;
871 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
872 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
873 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
874 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
875 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
876 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
877 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
878 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
879 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
880 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
881 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
882 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
883 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
884 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
885 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
886 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
887 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
888 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
889 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
890 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
891
892 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
893
894 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
895 }
896 rtcpParser.Iterate();
897}
898
899// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000900void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
901 RTCPPacketInformation& rtcpPacketInformation) {
902 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
903 if (_SSRC == rtcpPacket.PLI.MediaSSRC) {
904 // Received a signal that we need to send a new key frame.
905 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
906 }
907 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000908}
909
910// no need for critsect we have _criticalSectionRTCPReceiver
911void
912RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
913 RTCPPacketInformation& rtcpPacketInformation)
914{
915 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
916
917 WebRtc_UWord32 senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
918 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
919 if (ptrReceiveInfo == NULL)
920 {
921 // This remote SSRC must be saved before.
922 rtcpParser.Iterate();
923 return;
924 }
925 if(rtcpPacket.TMMBR.MediaSSRC)
926 {
927 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
928 // in relay mode this is a valid number
929 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
930 }
931
932 // Use packet length to calc max number of TMMBR blocks
933 // each TMMBR block is 8 bytes
934 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
935
936 // sanity
937 if(maxNumOfTMMBRBlocks > 200) // we can't have more than what's in one packet
938 {
939 assert(false);
940 rtcpParser.Iterate();
941 return;
942 }
943 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((WebRtc_UWord32)maxNumOfTMMBRBlocks);
944
945 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
946 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode)
947 {
948 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
949 pktType = rtcpParser.Iterate();
950 }
951}
952
953// no need for critsect we have _criticalSectionRTCPReceiver
954void
955RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
956 const RTCPUtility::RTCPPacket& rtcpPacket,
957 RTCPPacketInformation& rtcpPacketInformation,
958 const WebRtc_UWord32 senderSSRC)
959{
960 if (_SSRC == rtcpPacket.TMMBRItem.SSRC &&
961 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
962 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000963 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
964 _clock.GetTimeInMS());
niklase@google.com470e71d2011-07-07 08:21:25 +0000965 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
966 }
967}
968
969// no need for critsect we have _criticalSectionRTCPReceiver
970void
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000971RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
972 RTCPPacketInformation& rtcpPacketInformation)
niklase@google.com470e71d2011-07-07 08:21:25 +0000973{
974 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
975 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.TMMBN.SenderSSRC);
976 if (ptrReceiveInfo == NULL)
977 {
978 // This remote SSRC must be saved before.
979 rtcpParser.Iterate();
980 return;
981 }
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000982 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +0000983 // Use packet length to calc max number of TMMBN blocks
984 // each TMMBN block is 8 bytes
985 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
986
987 // sanity
988 if(maxNumOfTMMBNBlocks > 200) // we cant have more than what's in one packet
989 {
990 assert(false);
991 rtcpParser.Iterate();
992 return;
993 }
994
995 ptrReceiveInfo->VerifyAndAllocateBoundingSet((WebRtc_UWord32)maxNumOfTMMBNBlocks);
996
997 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
998 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode)
999 {
1000 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
1001 pktType = rtcpParser.Iterate();
1002 }
1003}
1004
1005// no need for critsect we have _criticalSectionRTCPReceiver
1006void
1007RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
1008 RTCPPacketInformation& rtcpPacketInformation)
1009{
1010 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
1011 rtcpParser.Iterate();
1012}
1013
1014// no need for critsect we have _criticalSectionRTCPReceiver
1015void
1016RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
1017 const RTCPUtility::RTCPPacket& rtcpPacket)
1018{
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001019 receiveInfo.TmmbnBoundingSet.AddEntry(
1020 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
1021 rtcpPacket.TMMBNItem.MeasuredOverhead,
1022 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001023}
1024
1025// no need for critsect we have _criticalSectionRTCPReceiver
1026void
1027RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
1028 RTCPPacketInformation& rtcpPacketInformation)
1029{
1030 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001031 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1032 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode)
1033 {
1034 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1035 pktType = rtcpParser.Iterate();
1036 }
1037}
1038
1039// no need for critsect we have _criticalSectionRTCPReceiver
1040void
1041RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1042 RTCPPacketInformation& rtcpPacketInformation)
1043{
1044 // in theory there could be multiple slices lost
1045 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1046 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
1047}
1048
1049void
1050RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1051 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1052{
1053 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001054 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1055 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1056 {
1057 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1058 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1059 {
1060 // to us unknown
1061 // continue
1062 rtcpParser.Iterate();
1063 return;
1064 }
1065 rtcpPacketInformation.rpsiPictureId = 0;
1066
1067 // convert NativeBitString to rpsiPictureId
1068 WebRtc_UWord8 numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1069 for(WebRtc_UWord8 n = 0; n < (numberOfBytes-1); n++)
1070 {
1071 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1072 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1073 }
1074 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1075 }
1076}
1077
1078// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001079void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1080 RTCPPacketInformation& rtcpPacketInformation) {
1081 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1082 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1083 pktType = rtcpParser.Iterate();
1084 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1085 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1086 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001087 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001088 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001089}
1090
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001091// no need for critsect we have _criticalSectionRTCPReceiver
1092void
1093RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1094 RTCPPacketInformation& rtcpPacketInformation)
1095{
1096 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1097
1098 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1099 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode)
1100 {
1101 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1102 pktType = rtcpParser.Iterate();
1103 }
1104}
1105
1106void
1107RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1108 RTCPPacketInformation& rtcpPacketInformation)
1109{
1110 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1111 rtcpPacketInformation.interArrivalJitter =
1112 rtcpPacket.ExtendedJitterReportItem.Jitter;
1113}
1114
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001115void RTCPReceiver::HandleREMBItem(
1116 RTCPUtility::RTCPParserV2& rtcpParser,
1117 RTCPPacketInformation& rtcpPacketInformation) {
1118 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1119 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1120 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1121 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001122}
1123
1124// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001125void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1126 RTCPPacketInformation& rtcpPacketInformation) {
1127 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1128 RTCPReceiveInformation* ptrReceiveInfo =
1129 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001130
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001131 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1132 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1133 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1134 pktType = rtcpParser.Iterate();
1135 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001136}
1137
1138// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001139void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1140 const RTCPUtility::RTCPPacket& rtcpPacket,
1141 RTCPPacketInformation& rtcpPacketInformation) {
1142 // Is it our sender that is requested to generate a new keyframe
1143 if (_SSRC != rtcpPacket.FIRItem.SSRC) {
1144 return;
1145 }
1146 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1147 // we don't know who this originate from
1148 if (receiveInfo) {
1149 // check if we have reported this FIRSequenceNumber before
1150 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1151 receiveInfo->lastFIRSequenceNumber) {
pwestin@webrtc.org18530052012-07-03 10:41:54 +00001152 WebRtc_Word64 now = _clock.GetTimeInMS();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001153 // sanity; don't go crazy with the callbacks
1154 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1155 receiveInfo->lastFIRRequest = now;
1156 receiveInfo->lastFIRSequenceNumber =
1157 rtcpPacket.FIRItem.CommandSequenceNumber;
1158 // received signal that we need to send a new key frame
1159 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1160 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001161 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001162 } else {
1163 // received signal that we need to send a new key frame
1164 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1165 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001166}
1167
1168void
1169RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1170 RTCPPacketInformation& rtcpPacketInformation)
1171{
1172 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1173
1174 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1175 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1176 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
1177
1178 rtcpParser.Iterate();
1179}
1180
1181void
1182RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1183 RTCPPacketInformation& rtcpPacketInformation)
1184{
1185 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1186
1187 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
1188
1189 rtcpParser.Iterate();
1190}
1191
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001192WebRtc_Word32 RTCPReceiver::UpdateTMMBR() {
1193 WebRtc_Word32 numBoundingSet = 0;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001194 WebRtc_UWord32 bitrate = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001195 WebRtc_UWord32 accNumCandidates = 0;
1196
1197 WebRtc_Word32 size = TMMBRReceived(0, 0, NULL);
1198 if (size > 0) {
1199 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1200 // Get candidate set from receiver.
1201 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1202 } else {
1203 // Candidate set empty.
1204 VerifyAndAllocateCandidateSet(0); // resets candidate set
1205 }
1206 // Find bounding set
1207 TMMBRSet* boundingSet = NULL;
1208 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1209 if (numBoundingSet == -1) {
1210 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1211 "Failed to find TMMBR bounding set.");
1212 return -1;
1213 }
1214 // Set bounding set
1215 // Inform remote clients about the new bandwidth
1216 // inform the remote client
1217 _rtpRtcp.SetTMMBN(boundingSet);
1218
1219 // might trigger a TMMBN
1220 if (numBoundingSet == 0) {
1221 // owner of max bitrate request has timed out
1222 // empty bounding set has been sent
1223 return 0;
1224 }
1225 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001226 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001227 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001228 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1229 if (_cbRtcpBandwidthObserver) {
1230 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
1231 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id,
1232 "Set TMMBR request:%d kbps", bitrate);
1233 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001234 }
1235 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001236}
1237
1238// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001239void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001240 RTCPPacketInformation& rtcpPacketInformation) {
1241 // Process TMMBR and REMB first to avoid multiple callbacks
1242 // to OnNetworkChanged.
1243 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
1244 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1245 "SIG [RTCP] Incoming TMMBR to id:%d", _id);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001246
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001247 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1248 UpdateTMMBR();
1249 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001250 unsigned int local_ssrc = 0;
1251 {
1252 // We don't want to hold this critsect when triggering the callbacks below.
1253 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1254 local_ssrc = _SSRC;
1255 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001256 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1257 _rtpRtcp.OnRequestSendReport();
1258 }
1259 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
1260 if (rtcpPacketInformation.nackSequenceNumbersLength > 0) {
1261 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1262 "SIG [RTCP] Incoming NACK length:%d",
1263 rtcpPacketInformation.nackSequenceNumbersLength);
1264 _rtpRtcp.OnReceivedNACK(
1265 rtcpPacketInformation.nackSequenceNumbersLength,
1266 rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001267 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001268 }
1269 {
1270 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001271
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001272 // We need feedback that we have received a report block(s) so that we
1273 // can generate a new packet in a conference relay scenario, one received
1274 // report can generate several RTCP packets, based on number relayed/mixed
1275 // a send report block should go out to all receivers.
1276 if (_cbRtcpIntraFrameObserver) {
1277 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1278 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1279 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
1280 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1281 "SIG [RTCP] Incoming PLI from SSRC:0x%x",
1282 rtcpPacketInformation.remoteSSRC);
1283 } else {
1284 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1285 "SIG [RTCP] Incoming FIR from SSRC:0x%x",
1286 rtcpPacketInformation.remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001287 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001288 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001289 }
1290 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1291 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001292 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001293 }
1294 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1295 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001296 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001297 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001298 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001299 if (_cbRtcpBandwidthObserver) {
1300 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
1301 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1302 "SIG [RTCP] Incoming REMB:%d",
1303 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1304 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1305 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1306 }
1307 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1308 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) &&
1309 rtcpPacketInformation.reportBlock) {
pwestin@webrtc.org18530052012-07-03 10:41:54 +00001310 WebRtc_Word64 now = _clock.GetTimeInMS();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001311 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
1312 rtcpPacketInformation.remoteSSRC,
1313 rtcpPacketInformation.fractionLost,
1314 rtcpPacketInformation.roundTripTime,
1315 rtcpPacketInformation.lastReceivedExtendedHighSeqNum,
1316 now);
1317 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001318 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001319 if(_cbRtcpFeedback) {
1320 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr) {
1321 _cbRtcpFeedback->OnSendReportReceived(_id,
stefan@webrtc.org976a7e62012-09-21 13:20:21 +00001322 rtcpPacketInformation.remoteSSRC,
1323 rtcpPacketInformation.ntp_secs,
1324 rtcpPacketInformation.ntp_frac,
1325 rtcpPacketInformation.rtp_timestamp);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001326 } else {
1327 _cbRtcpFeedback->OnReceiveReportReceived(_id,
1328 rtcpPacketInformation.remoteSSRC);
1329 }
1330 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpXrVoipMetric) {
1331 _cbRtcpFeedback->OnXRVoIPMetricReceived(_id,
1332 rtcpPacketInformation.VoIPMetric);
1333 }
1334 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpApp) {
1335 _cbRtcpFeedback->OnApplicationDataReceived(_id,
1336 rtcpPacketInformation.applicationSubType,
1337 rtcpPacketInformation.applicationName,
1338 rtcpPacketInformation.applicationLength,
1339 rtcpPacketInformation.applicationData);
1340 }
1341 }
1342 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001343}
1344
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001345WebRtc_Word32 RTCPReceiver::CNAME(const WebRtc_UWord32 remoteSSRC,
1346 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001347 assert(cName);
1348
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001349 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1350 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001351 if (cnameInfo == NULL) {
1352 return -1;
1353 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001354 cName[RTCP_CNAME_SIZE - 1] = 0;
1355 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1356 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001357}
1358
1359// no callbacks allowed inside this function
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001360WebRtc_Word32 RTCPReceiver::TMMBRReceived(const WebRtc_UWord32 size,
1361 const WebRtc_UWord32 accNumCandidates,
1362 TMMBRSet* candidateSet) const {
1363 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001364
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001365 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::const_iterator
1366 receiveInfoIt = _receivedInfoMap.begin();
1367 if (receiveInfoIt == _receivedInfoMap.end()) {
1368 return -1;
1369 }
1370 WebRtc_UWord32 num = accNumCandidates;
1371 if (candidateSet) {
1372 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1373 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1374 if (receiveInfo == NULL) {
1375 return 0;
1376 }
1377 for (WebRtc_UWord32 i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001378 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001379 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
1380 _clock.GetTimeInMS()) == 0) {
1381 num++;
1382 }
1383 }
1384 receiveInfoIt++;
1385 }
1386 } else {
1387 while (receiveInfoIt != _receivedInfoMap.end()) {
1388 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1389 if(receiveInfo == NULL) {
1390 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
1391 "%s failed to get RTCPReceiveInformation",
1392 __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +00001393 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001394 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001395 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001396 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001397 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001398 }
1399 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001400}
1401
1402WebRtc_Word32
1403RTCPReceiver::SetPacketTimeout(const WebRtc_UWord32 timeoutMS)
1404{
1405 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1406 _packetTimeOutMS = timeoutMS;
1407 return 0;
1408}
1409
1410void RTCPReceiver::PacketTimeout()
1411{
1412 if(_packetTimeOutMS == 0)
1413 {
1414 // not configured
1415 return;
1416 }
1417
1418 bool packetTimeOut = false;
1419 {
1420 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1421 if(_lastReceived == 0)
1422 {
1423 // not active
1424 return;
1425 }
1426
pwestin@webrtc.org18530052012-07-03 10:41:54 +00001427 WebRtc_Word64 now = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +00001428 if(now - _lastReceived > _packetTimeOutMS)
1429 {
1430 packetTimeOut = true;
1431 _lastReceived = 0; // only one callback
1432 }
1433 }
1434 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1435 if(packetTimeOut && _cbRtcpFeedback)
1436 {
1437 _cbRtcpFeedback->OnRTCPPacketTimeout(_id);
1438 }
1439}
1440} // namespace webrtc