blob: 7d80d181d51dba42317bc3497061ef2530ff6f90 [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
104WebRtc_UWord32
105RTCPReceiver::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
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000136void RTCPReceiver::SetSSRC( const WebRtc_UWord32 ssrc) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000137 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
138 _SSRC = ssrc;
139}
140
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000141WebRtc_Word32 RTCPReceiver::ResetRTT(const WebRtc_UWord32 remoteSSRC) {
142 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
143 RTCPReportBlockInformation* reportBlock =
144 GetReportBlockInformation(remoteSSRC);
145 if (reportBlock == NULL) {
146 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
147 "\tfailed to GetReportBlockInformation(%u)", remoteSSRC);
148 return -1;
149 }
150 reportBlock->RTT = 0;
151 reportBlock->avgRTT = 0;
152 reportBlock->minRTT = 0;
153 reportBlock->maxRTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000154 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000155}
156
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000157WebRtc_Word32 RTCPReceiver::RTT(const WebRtc_UWord32 remoteSSRC,
158 WebRtc_UWord16* RTT,
159 WebRtc_UWord16* avgRTT,
160 WebRtc_UWord16* minRTT,
161 WebRtc_UWord16* maxRTT) const {
162 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000163
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000164 RTCPReportBlockInformation* reportBlock =
165 GetReportBlockInformation(remoteSSRC);
166
167 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000168 return -1;
169 }
170 if (RTT) {
171 *RTT = reportBlock->RTT;
172 }
173 if (avgRTT) {
174 *avgRTT = reportBlock->avgRTT;
175 }
176 if (minRTT) {
177 *minRTT = reportBlock->minRTT;
178 }
179 if (maxRTT) {
180 *maxRTT = reportBlock->maxRTT;
181 }
182 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000183}
184
mflodman@webrtc.orgd7d46882012-02-14 12:49:59 +0000185WebRtc_UWord16 RTCPReceiver::RTT() const {
186 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
187 if (!_receivedReportBlockMap.empty()) {
188 return 0;
189 }
190 return _rtt;
191}
192
193int RTCPReceiver::SetRTT(WebRtc_UWord16 rtt) {
194 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
195 if (!_receivedReportBlockMap.empty()) {
196 return -1;
197 }
198 _rtt = rtt;
199 return 0;
200}
201
niklase@google.com470e71d2011-07-07 08:21:25 +0000202WebRtc_Word32
203RTCPReceiver::NTP(WebRtc_UWord32 *ReceivedNTPsecs,
204 WebRtc_UWord32 *ReceivedNTPfrac,
205 WebRtc_UWord32 *RTCPArrivalTimeSecs,
206 WebRtc_UWord32 *RTCPArrivalTimeFrac) const
207{
208 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
209 if(ReceivedNTPsecs)
210 {
211 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
212 }
213 if(ReceivedNTPfrac)
214 {
215 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
216 }
217 if(RTCPArrivalTimeFrac)
218 {
219 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
220 }
221 if(RTCPArrivalTimeSecs)
222 {
223 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
224 }
225 return 0;
226}
227
228WebRtc_Word32
229RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const
230{
231 if(senderInfo == NULL)
232 {
233 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
234 return -1;
235 }
236 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
237 if(_lastReceivedSRNTPsecs == 0)
238 {
239 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s No received SR", __FUNCTION__);
240 return -1;
241 }
242 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
243 return 0;
244}
245
246// statistics
247// we can get multiple receive reports when we receive the report from a CE
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000248WebRtc_Word32 RTCPReceiver::StatisticsReceived(
249 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000250 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000251 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
252
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000253 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::const_iterator it =
254 _receivedReportBlockMap.begin();
255
256 while (it != _receivedReportBlockMap.end()) {
257 receiveBlocks->push_back(it->second->remoteReceiveBlock);
258 it++;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000259 }
260 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000261}
262
263WebRtc_Word32
264RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
265 RTCPUtility::RTCPParserV2* rtcpParser)
266{
267 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
268
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000269 _lastReceived = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000270
271 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
272 while (pktType != RTCPUtility::kRtcpNotValidCode)
273 {
274 // Each "case" is responsible for iterate the parser to the
275 // next top level packet.
276 switch (pktType)
277 {
278 case RTCPUtility::kRtcpSrCode:
279 case RTCPUtility::kRtcpRrCode:
280 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
281 break;
282 case RTCPUtility::kRtcpSdesCode:
283 HandleSDES(*rtcpParser);
284 break;
285 case RTCPUtility::kRtcpXrVoipMetricCode:
286 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
287 break;
288 case RTCPUtility::kRtcpByeCode:
289 HandleBYE(*rtcpParser);
290 break;
291 case RTCPUtility::kRtcpRtpfbNackCode:
292 HandleNACK(*rtcpParser, rtcpPacketInformation);
293 break;
294 case RTCPUtility::kRtcpRtpfbTmmbrCode:
295 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
296 break;
297 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000298 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000299 break;
300 case RTCPUtility::kRtcpRtpfbSrReqCode:
301 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
302 break;
303 case RTCPUtility::kRtcpPsfbPliCode:
304 HandlePLI(*rtcpParser, rtcpPacketInformation);
305 break;
306 case RTCPUtility::kRtcpPsfbSliCode:
307 HandleSLI(*rtcpParser, rtcpPacketInformation);
308 break;
309 case RTCPUtility::kRtcpPsfbRpsiCode:
310 HandleRPSI(*rtcpParser, rtcpPacketInformation);
311 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000312 case RTCPUtility::kRtcpExtendedIjCode:
313 HandleIJ(*rtcpParser, rtcpPacketInformation);
314 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000315 case RTCPUtility::kRtcpPsfbFirCode:
316 HandleFIR(*rtcpParser, rtcpPacketInformation);
317 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000318 case RTCPUtility::kRtcpPsfbAppCode:
319 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
320 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000321 case RTCPUtility::kRtcpAppCode:
322 // generic application messages
323 HandleAPP(*rtcpParser, rtcpPacketInformation);
324 break;
325 case RTCPUtility::kRtcpAppItemCode:
326 // generic application messages
327 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
328 break;
329 default:
330 rtcpParser->Iterate();
331 break;
332 }
333 pktType = rtcpParser->PacketType();
334 }
335 return 0;
336}
337
338// no need for critsect we have _criticalSectionRTCPReceiver
339void
340RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
341 RTCPPacketInformation& rtcpPacketInformation)
342{
343 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
344 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
345
346 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
347
348 // SR.SenderSSRC
349 // The synchronization source identifier for the originator of this SR packet
350
351 // rtcpPacket.RR.SenderSSRC
352 // The source of the packet sender, same as of SR? or is this a CE?
353
354 const WebRtc_UWord32 remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
355 const WebRtc_UWord8 numberOfReportBlocks = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.NumberOfReportBlocks:rtcpPacket.SR.NumberOfReportBlocks;
356
357 rtcpPacketInformation.remoteSSRC = remoteSSRC;
358
359 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
360 if (!ptrReceiveInfo)
361 {
362 rtcpParser.Iterate();
363 return;
364 }
365
366 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
367 {
368 WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
369 "Received SR(%d). SSRC:0x%x, from SSRC:0x%x, to us %d.", _id, _SSRC, remoteSSRC, (_remoteSSRC == remoteSSRC)?1:0);
370
371 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
372 {
373 // only signal that we have received a SR when we accept one
374 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
375
376 // We will only store the send report from one source, but
377 // we will store all the receive block
378
379 // Save the NTP time of this report
380 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
381 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
382 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
383 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
384 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
385
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000386 _clock.CurrentNTP(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000387 }
388 else
389 {
390 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
391 }
392 } else
393 {
394 WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
395 "Received RR(%d). SSRC:0x%x, from SSRC:0x%x", _id, _SSRC, remoteSSRC);
396
397 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
398 }
399 UpdateReceiveInformation(*ptrReceiveInfo);
400
401 rtcpPacketType = rtcpParser.Iterate();
402
403 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
404 {
405 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC, numberOfReportBlocks);
406 rtcpPacketType = rtcpParser.Iterate();
407 }
408}
409
410// no need for critsect we have _criticalSectionRTCPReceiver
411void
412RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
413 RTCPPacketInformation& rtcpPacketInformation,
414 const WebRtc_UWord32 remoteSSRC,
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000415 const WebRtc_UWord8 numberOfReportBlocks) {
416 // This will be called once per report block in the RTCP packet.
417 // We filter out all report blocks that are not for us.
418 // Each packet has max 31 RR blocks.
419 //
420 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000421
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000422 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
423 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000424
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000425 // Filter out all report blocks that are not for us.
426 if (rtcpPacket.ReportBlockItem.SSRC != _SSRC) {
427 // This block is not for us ignore it.
428 return;
429 }
430
431 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
432 // _criticalSectionRTCPReceiver.
433 _criticalSectionRTCPReceiver->Leave();
434 WebRtc_UWord32 sendTimeMS =
435 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
436 _criticalSectionRTCPReceiver->Enter();
437
438 RTCPReportBlockInformation* reportBlock =
439 CreateReportBlockInformation(remoteSSRC);
440 if (reportBlock == NULL) {
441 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
442 "\tfailed to CreateReportBlockInformation(%u)", remoteSSRC);
443 return;
444 }
445 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
446 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
447 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
448 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
449 reportBlock->remoteReceiveBlock.cumulativeLost =
450 rb.CumulativeNumOfPacketsLost;
451 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
452 rb.ExtendedHighestSequenceNumber;
453 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
454 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
455 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
456
457 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
458 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
459 }
460
461 WebRtc_UWord32 delaySinceLastSendReport =
462 rtcpPacket.ReportBlockItem.DelayLastSR;
463
464 // local NTP time when we received this
465 WebRtc_UWord32 lastReceivedRRNTPsecs = 0;
466 WebRtc_UWord32 lastReceivedRRNTPfrac = 0;
467
468 _clock.CurrentNTP(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
469
470 // time when we received this in MS
471 WebRtc_UWord32 receiveTimeMS = ModuleRTPUtility::ConvertNTPTimeToMS(
472 lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
473
474 // Estimate RTT
475 WebRtc_UWord32 d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
476 d /= 65536;
477 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
478
479 WebRtc_Word32 RTT = 0;
480
481 if (sendTimeMS > 0) {
482 RTT = receiveTimeMS - d - sendTimeMS;
483 if (RTT <= 0) {
484 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000485 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000486 if (RTT > reportBlock->maxRTT) {
487 // store max RTT
488 reportBlock->maxRTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000489 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000490 if (reportBlock->minRTT == 0) {
491 // first RTT
492 reportBlock->minRTT = (WebRtc_UWord16) RTT;
493 } else if (RTT < reportBlock->minRTT) {
494 // Store min RTT
495 reportBlock->minRTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000496 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000497 // store last RTT
498 reportBlock->RTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000499
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000500 // store average RTT
501 if (reportBlock->numAverageCalcs != 0) {
502 float ac = static_cast<float> (reportBlock->numAverageCalcs);
503 float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT)
504 + ((1 / (ac + 1)) * RTT);
505 reportBlock->avgRTT = static_cast<int> (newAverage + 0.5f);
506 } else {
507 // first RTT
508 reportBlock->avgRTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000509 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000510 reportBlock->numAverageCalcs++;
511 }
512
513 WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
514 " -> Received report block(%d), from SSRC:0x%x, RTT:%d, loss:%d",
515 _id, remoteSSRC, RTT, rtcpPacket.ReportBlockItem.FractionLost);
516
517 // rtcpPacketInformation
518 rtcpPacketInformation.AddReportInfo(
519 reportBlock->remoteReceiveBlock.fractionLost, (WebRtc_UWord16) RTT,
520 reportBlock->remoteReceiveBlock.extendedHighSeqNum,
521 reportBlock->remoteReceiveBlock.jitter);
niklase@google.com470e71d2011-07-07 08:21:25 +0000522}
523
524RTCPReportBlockInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000525RTCPReceiver::CreateReportBlockInformation(WebRtc_UWord32 remoteSSRC) {
526 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000527
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000528 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::iterator it =
529 _receivedReportBlockMap.find(remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000530
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000531 RTCPReportBlockInformation* ptrReportBlockInfo = NULL;
532 if (it != _receivedReportBlockMap.end()) {
533 ptrReportBlockInfo = it->second;
534 } else {
535 ptrReportBlockInfo = new RTCPReportBlockInformation;
536 _receivedReportBlockMap[remoteSSRC] = ptrReportBlockInfo;
537 }
538 return ptrReportBlockInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000539}
540
541RTCPReportBlockInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000542RTCPReceiver::GetReportBlockInformation(WebRtc_UWord32 remoteSSRC) const {
543 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000544
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000545 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::const_iterator it =
546 _receivedReportBlockMap.find(remoteSSRC);
547
548 if (it == _receivedReportBlockMap.end()) {
549 return NULL;
550 }
551 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000552}
553
554RTCPCnameInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000555RTCPReceiver::CreateCnameInformation(WebRtc_UWord32 remoteSSRC) {
556 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000557
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000558 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator it =
559 _receivedCnameMap.find(remoteSSRC);
560
561 if (it != _receivedCnameMap.end()) {
562 return it->second;
563 }
564 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000565 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000566 _receivedCnameMap[remoteSSRC] = cnameInfo;
567 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000568}
569
570RTCPCnameInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000571RTCPReceiver::GetCnameInformation(WebRtc_UWord32 remoteSSRC) const {
572 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000573
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000574 std::map<WebRtc_UWord32, RTCPCnameInformation*>::const_iterator it =
575 _receivedCnameMap.find(remoteSSRC);
576
577 if (it == _receivedCnameMap.end()) {
578 return NULL;
579 }
580 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000581}
582
583RTCPReceiveInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000584RTCPReceiver::CreateReceiveInformation(WebRtc_UWord32 remoteSSRC) {
585 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000586
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000587 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator it =
588 _receivedInfoMap.find(remoteSSRC);
589
590 if (it != _receivedInfoMap.end()) {
591 return it->second;
592 }
593 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
594 _receivedInfoMap[remoteSSRC] = receiveInfo;
595 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000596}
597
598RTCPReceiveInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000599RTCPReceiver::GetReceiveInformation(WebRtc_UWord32 remoteSSRC) {
600 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000601
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000602 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator it =
603 _receivedInfoMap.find(remoteSSRC);
604 if (it == _receivedInfoMap.end()) {
605 return NULL;
606 }
607 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000608}
609
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000610void RTCPReceiver::UpdateReceiveInformation(
611 RTCPReceiveInformation& receiveInformation) {
612 // Update that this remote is alive
613 receiveInformation.lastTimeReceived = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000614}
615
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000616bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
617 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000618
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000619 bool updateBoundingSet = false;
620 WebRtc_UWord32 timeNow = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000621
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000622 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator receiveInfoIt =
623 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000624
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000625 while (receiveInfoIt != _receivedInfoMap.end()) {
626 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
627 if (receiveInfo == NULL) {
628 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000629 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000630 // time since last received rtcp packet
631 // when we dont have a lastTimeReceived and the object is marked
632 // readyForDelete it's removed from the map
633 if (receiveInfo->lastTimeReceived) {
634 /// use audio define since we don't know what interval the remote peer is
635 // using
636 if ((timeNow - receiveInfo->lastTimeReceived) >
637 5 * RTCP_INTERVAL_AUDIO_MS) {
638 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000639 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000640 // prevent that we call this over and over again
641 receiveInfo->lastTimeReceived = 0;
642 // send new TMMBN to all channels using the default codec
643 updateBoundingSet = true;
644 }
645 receiveInfoIt++;
646 } else if (receiveInfo->readyForDelete) {
647 // store our current receiveInfoItem
648 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator
649 receiveInfoItemToBeErased = receiveInfoIt;
650 receiveInfoIt++;
651 delete receiveInfoItemToBeErased->second;
652 _receivedInfoMap.erase(receiveInfoItemToBeErased);
653 } else {
654 receiveInfoIt++;
655 }
656 }
657 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000658}
659
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000660WebRtc_Word32 RTCPReceiver::BoundingSet(bool &tmmbrOwner,
hta@webrtc.org65a4e4e2012-04-30 11:23:41 +0000661 TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000662 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000663
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000664 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator receiveInfoIt =
665 _receivedInfoMap.find(_remoteSSRC);
666
667 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000668 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000669 }
670 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
671 if (receiveInfo == NULL) {
672 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
673 "%s failed to get RTCPReceiveInformation",
674 __FUNCTION__);
675 return -1;
676 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000677 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000678 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000679 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
680 for(WebRtc_UWord32 i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
681 i++) {
682 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == _SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000683 // owner of bounding set
684 tmmbrOwner = true;
685 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000686 boundingSetRec->SetEntry(i,
687 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
688 receiveInfo->TmmbnBoundingSet.PacketOH(i),
689 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000690 }
691 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000692 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000693}
694
695// no need for critsect we have _criticalSectionRTCPReceiver
696void
697RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser)
698{
699 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
700 while (pktType == RTCPUtility::kRtcpSdesChunkCode)
701 {
702 HandleSDESChunk(rtcpParser);
703 pktType = rtcpParser.Iterate();
704 }
705}
706
707// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000708void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
709 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
710 RTCPCnameInformation* cnameInfo =
711 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
712 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000713
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000714 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
715 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000716}
717
718// no need for critsect we have _criticalSectionRTCPReceiver
719void
720RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
721 RTCPPacketInformation& rtcpPacketInformation)
722{
723 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000724 if (_SSRC != rtcpPacket.NACK.MediaSSRC)
725 {
726 // Not to us.
727 rtcpParser.Iterate();
728 return;
729 }
730
731 rtcpPacketInformation.ResetNACKPacketIdArray();
732
733 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
734 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode)
735 {
736 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
737 pktType = rtcpParser.Iterate();
738 }
739}
740
741// no need for critsect we have _criticalSectionRTCPReceiver
742void
743RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
744 RTCPPacketInformation& rtcpPacketInformation)
745{
746 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
747
748 WebRtc_UWord16 bitMask = rtcpPacket.NACKItem.BitMask;
749 if(bitMask)
750 {
751 for(int i=1; i <= 16; ++i)
752 {
753 if(bitMask & 0x01)
754 {
755 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
756 }
757 bitMask = bitMask >>1;
758 }
759 }
760
761 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
762}
763
764// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000765void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
766 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000767
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000768 // clear our lists
769 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
770 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::iterator
771 reportBlockInfoIt = _receivedReportBlockMap.find(
772 rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000773
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000774 if (reportBlockInfoIt != _receivedReportBlockMap.end()) {
775 delete reportBlockInfoIt->second;
776 _receivedReportBlockMap.erase(reportBlockInfoIt);
777 }
778 // we can't delete it due to TMMBR
779 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator receiveInfoIt =
780 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000781
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000782 if (receiveInfoIt != _receivedInfoMap.end()) {
783 receiveInfoIt->second->readyForDelete = true;
784 }
785
786 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator cnameInfoIt =
787 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
788
789 if (cnameInfoIt != _receivedCnameMap.end()) {
790 delete cnameInfoIt->second;
791 _receivedCnameMap.erase(cnameInfoIt);
792 }
793 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000794}
795
796// no need for critsect we have _criticalSectionRTCPReceiver
797void
798RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
799 RTCPPacketInformation& rtcpPacketInformation)
800{
801 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
802
803 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
804
805 if(rtcpPacket.XRVOIPMetricItem.SSRC == _SSRC)
806 {
807 // Store VoIP metrics block if it's about me
808 // from OriginatorSSRC do we filter it?
809 // rtcpPacket.XR.OriginatorSSRC;
810
811 RTCPVoIPMetric receivedVoIPMetrics;
812 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
813 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
814 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
815 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
816 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
817 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
818 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
819 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
820 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
821 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
822 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
823 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
824 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
825 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
826 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
827 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
828 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
829 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
830 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
831 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
832
833 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
834
835 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
836 }
837 rtcpParser.Iterate();
838}
839
840// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000841void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
842 RTCPPacketInformation& rtcpPacketInformation) {
843 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
844 if (_SSRC == rtcpPacket.PLI.MediaSSRC) {
845 // Received a signal that we need to send a new key frame.
846 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
847 }
848 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000849}
850
851// no need for critsect we have _criticalSectionRTCPReceiver
852void
853RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
854 RTCPPacketInformation& rtcpPacketInformation)
855{
856 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
857
858 WebRtc_UWord32 senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
859 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
860 if (ptrReceiveInfo == NULL)
861 {
862 // This remote SSRC must be saved before.
863 rtcpParser.Iterate();
864 return;
865 }
866 if(rtcpPacket.TMMBR.MediaSSRC)
867 {
868 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
869 // in relay mode this is a valid number
870 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
871 }
872
873 // Use packet length to calc max number of TMMBR blocks
874 // each TMMBR block is 8 bytes
875 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
876
877 // sanity
878 if(maxNumOfTMMBRBlocks > 200) // we can't have more than what's in one packet
879 {
880 assert(false);
881 rtcpParser.Iterate();
882 return;
883 }
884 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((WebRtc_UWord32)maxNumOfTMMBRBlocks);
885
886 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
887 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode)
888 {
889 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
890 pktType = rtcpParser.Iterate();
891 }
892}
893
894// no need for critsect we have _criticalSectionRTCPReceiver
895void
896RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
897 const RTCPUtility::RTCPPacket& rtcpPacket,
898 RTCPPacketInformation& rtcpPacketInformation,
899 const WebRtc_UWord32 senderSSRC)
900{
901 if (_SSRC == rtcpPacket.TMMBRItem.SSRC &&
902 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
903 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000904 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
905 _clock.GetTimeInMS());
niklase@google.com470e71d2011-07-07 08:21:25 +0000906 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
907 }
908}
909
910// no need for critsect we have _criticalSectionRTCPReceiver
911void
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000912RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
913 RTCPPacketInformation& rtcpPacketInformation)
niklase@google.com470e71d2011-07-07 08:21:25 +0000914{
915 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
916 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.TMMBN.SenderSSRC);
917 if (ptrReceiveInfo == NULL)
918 {
919 // This remote SSRC must be saved before.
920 rtcpParser.Iterate();
921 return;
922 }
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000923 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +0000924 // Use packet length to calc max number of TMMBN blocks
925 // each TMMBN block is 8 bytes
926 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
927
928 // sanity
929 if(maxNumOfTMMBNBlocks > 200) // we cant have more than what's in one packet
930 {
931 assert(false);
932 rtcpParser.Iterate();
933 return;
934 }
935
936 ptrReceiveInfo->VerifyAndAllocateBoundingSet((WebRtc_UWord32)maxNumOfTMMBNBlocks);
937
938 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
939 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode)
940 {
941 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
942 pktType = rtcpParser.Iterate();
943 }
944}
945
946// no need for critsect we have _criticalSectionRTCPReceiver
947void
948RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
949 RTCPPacketInformation& rtcpPacketInformation)
950{
951 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
952 rtcpParser.Iterate();
953}
954
955// no need for critsect we have _criticalSectionRTCPReceiver
956void
957RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
958 const RTCPUtility::RTCPPacket& rtcpPacket)
959{
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000960 receiveInfo.TmmbnBoundingSet.AddEntry(
961 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
962 rtcpPacket.TMMBNItem.MeasuredOverhead,
963 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000964}
965
966// no need for critsect we have _criticalSectionRTCPReceiver
967void
968RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
969 RTCPPacketInformation& rtcpPacketInformation)
970{
971 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000972 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
973 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode)
974 {
975 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
976 pktType = rtcpParser.Iterate();
977 }
978}
979
980// no need for critsect we have _criticalSectionRTCPReceiver
981void
982RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
983 RTCPPacketInformation& rtcpPacketInformation)
984{
985 // in theory there could be multiple slices lost
986 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
987 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
988}
989
990void
991RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
992 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
993{
994 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000995 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
996 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
997 {
998 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
999 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1000 {
1001 // to us unknown
1002 // continue
1003 rtcpParser.Iterate();
1004 return;
1005 }
1006 rtcpPacketInformation.rpsiPictureId = 0;
1007
1008 // convert NativeBitString to rpsiPictureId
1009 WebRtc_UWord8 numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1010 for(WebRtc_UWord8 n = 0; n < (numberOfBytes-1); n++)
1011 {
1012 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1013 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1014 }
1015 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1016 }
1017}
1018
1019// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001020void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1021 RTCPPacketInformation& rtcpPacketInformation) {
1022 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1023 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1024 pktType = rtcpParser.Iterate();
1025 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1026 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1027 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001028 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001029 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001030}
1031
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001032// no need for critsect we have _criticalSectionRTCPReceiver
1033void
1034RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1035 RTCPPacketInformation& rtcpPacketInformation)
1036{
1037 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1038
1039 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1040 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode)
1041 {
1042 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1043 pktType = rtcpParser.Iterate();
1044 }
1045}
1046
1047void
1048RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1049 RTCPPacketInformation& rtcpPacketInformation)
1050{
1051 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1052 rtcpPacketInformation.interArrivalJitter =
1053 rtcpPacket.ExtendedJitterReportItem.Jitter;
1054}
1055
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001056void RTCPReceiver::HandleREMBItem(
1057 RTCPUtility::RTCPParserV2& rtcpParser,
1058 RTCPPacketInformation& rtcpPacketInformation) {
1059 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1060 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1061 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1062 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001063}
1064
1065// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001066void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1067 RTCPPacketInformation& rtcpPacketInformation) {
1068 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1069 RTCPReceiveInformation* ptrReceiveInfo =
1070 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001071
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001072 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1073 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1074 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1075 pktType = rtcpParser.Iterate();
1076 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001077}
1078
1079// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001080void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1081 const RTCPUtility::RTCPPacket& rtcpPacket,
1082 RTCPPacketInformation& rtcpPacketInformation) {
1083 // Is it our sender that is requested to generate a new keyframe
1084 if (_SSRC != rtcpPacket.FIRItem.SSRC) {
1085 return;
1086 }
1087 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1088 // we don't know who this originate from
1089 if (receiveInfo) {
1090 // check if we have reported this FIRSequenceNumber before
1091 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1092 receiveInfo->lastFIRSequenceNumber) {
1093 WebRtc_UWord32 now = _clock.GetTimeInMS();
1094 // sanity; don't go crazy with the callbacks
1095 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1096 receiveInfo->lastFIRRequest = now;
1097 receiveInfo->lastFIRSequenceNumber =
1098 rtcpPacket.FIRItem.CommandSequenceNumber;
1099 // received signal that we need to send a new key frame
1100 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1101 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001102 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001103 } else {
1104 // received signal that we need to send a new key frame
1105 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1106 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001107}
1108
1109void
1110RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1111 RTCPPacketInformation& rtcpPacketInformation)
1112{
1113 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1114
1115 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1116 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1117 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
1118
1119 rtcpParser.Iterate();
1120}
1121
1122void
1123RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1124 RTCPPacketInformation& rtcpPacketInformation)
1125{
1126 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1127
1128 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
1129
1130 rtcpParser.Iterate();
1131}
1132
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001133WebRtc_Word32 RTCPReceiver::UpdateTMMBR() {
1134 WebRtc_Word32 numBoundingSet = 0;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001135 WebRtc_UWord32 bitrate = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001136 WebRtc_UWord32 accNumCandidates = 0;
1137
1138 WebRtc_Word32 size = TMMBRReceived(0, 0, NULL);
1139 if (size > 0) {
1140 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1141 // Get candidate set from receiver.
1142 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1143 } else {
1144 // Candidate set empty.
1145 VerifyAndAllocateCandidateSet(0); // resets candidate set
1146 }
1147 // Find bounding set
1148 TMMBRSet* boundingSet = NULL;
1149 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1150 if (numBoundingSet == -1) {
1151 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1152 "Failed to find TMMBR bounding set.");
1153 return -1;
1154 }
1155 // Set bounding set
1156 // Inform remote clients about the new bandwidth
1157 // inform the remote client
1158 _rtpRtcp.SetTMMBN(boundingSet);
1159
1160 // might trigger a TMMBN
1161 if (numBoundingSet == 0) {
1162 // owner of max bitrate request has timed out
1163 // empty bounding set has been sent
1164 return 0;
1165 }
1166 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001167 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001168 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001169 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1170 if (_cbRtcpBandwidthObserver) {
1171 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
1172 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id,
1173 "Set TMMBR request:%d kbps", bitrate);
1174 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001175 }
1176 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001177}
1178
1179// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001180void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001181 RTCPPacketInformation& rtcpPacketInformation) {
1182 // Process TMMBR and REMB first to avoid multiple callbacks
1183 // to OnNetworkChanged.
1184 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
1185 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1186 "SIG [RTCP] Incoming TMMBR to id:%d", _id);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001187
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001188 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1189 UpdateTMMBR();
1190 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001191 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1192 _rtpRtcp.OnRequestSendReport();
1193 }
1194 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
1195 if (rtcpPacketInformation.nackSequenceNumbersLength > 0) {
1196 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1197 "SIG [RTCP] Incoming NACK length:%d",
1198 rtcpPacketInformation.nackSequenceNumbersLength);
1199 _rtpRtcp.OnReceivedNACK(
1200 rtcpPacketInformation.nackSequenceNumbersLength,
1201 rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001202 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001203 }
1204 {
1205 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001206
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001207 // We need feedback that we have received a report block(s) so that we
1208 // can generate a new packet in a conference relay scenario, one received
1209 // report can generate several RTCP packets, based on number relayed/mixed
1210 // a send report block should go out to all receivers.
1211 if (_cbRtcpIntraFrameObserver) {
1212 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1213 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1214 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
1215 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1216 "SIG [RTCP] Incoming PLI from SSRC:0x%x",
1217 rtcpPacketInformation.remoteSSRC);
1218 } else {
1219 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1220 "SIG [RTCP] Incoming FIR from SSRC:0x%x",
1221 rtcpPacketInformation.remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001222 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001223 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(
1224 rtcpPacketInformation.remoteSSRC);
1225 }
1226 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1227 _cbRtcpIntraFrameObserver->OnReceivedSLI(
1228 rtcpPacketInformation.remoteSSRC,
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00001229 rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001230 }
1231 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1232 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
1233 rtcpPacketInformation.remoteSSRC,
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001234 rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001235 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001236 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001237 if (_cbRtcpBandwidthObserver) {
1238 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
1239 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1240 "SIG [RTCP] Incoming REMB:%d",
1241 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1242 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1243 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1244 }
1245 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1246 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) &&
1247 rtcpPacketInformation.reportBlock) {
1248 WebRtc_UWord32 now = _clock.GetTimeInMS();
1249 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
1250 rtcpPacketInformation.remoteSSRC,
1251 rtcpPacketInformation.fractionLost,
1252 rtcpPacketInformation.roundTripTime,
1253 rtcpPacketInformation.lastReceivedExtendedHighSeqNum,
1254 now);
1255 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001256 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001257 if(_cbRtcpFeedback) {
1258 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr) {
1259 _cbRtcpFeedback->OnSendReportReceived(_id,
1260 rtcpPacketInformation.remoteSSRC);
1261 } else {
1262 _cbRtcpFeedback->OnReceiveReportReceived(_id,
1263 rtcpPacketInformation.remoteSSRC);
1264 }
1265 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpXrVoipMetric) {
1266 _cbRtcpFeedback->OnXRVoIPMetricReceived(_id,
1267 rtcpPacketInformation.VoIPMetric);
1268 }
1269 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpApp) {
1270 _cbRtcpFeedback->OnApplicationDataReceived(_id,
1271 rtcpPacketInformation.applicationSubType,
1272 rtcpPacketInformation.applicationName,
1273 rtcpPacketInformation.applicationLength,
1274 rtcpPacketInformation.applicationData);
1275 }
1276 }
1277 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001278}
1279
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001280WebRtc_Word32 RTCPReceiver::CNAME(const WebRtc_UWord32 remoteSSRC,
1281 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001282 assert(cName);
1283
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001284 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1285 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001286 if (cnameInfo == NULL) {
1287 return -1;
1288 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001289 cName[RTCP_CNAME_SIZE - 1] = 0;
1290 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1291 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001292}
1293
1294// no callbacks allowed inside this function
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001295WebRtc_Word32 RTCPReceiver::TMMBRReceived(const WebRtc_UWord32 size,
1296 const WebRtc_UWord32 accNumCandidates,
1297 TMMBRSet* candidateSet) const {
1298 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001299
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001300 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::const_iterator
1301 receiveInfoIt = _receivedInfoMap.begin();
1302 if (receiveInfoIt == _receivedInfoMap.end()) {
1303 return -1;
1304 }
1305 WebRtc_UWord32 num = accNumCandidates;
1306 if (candidateSet) {
1307 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1308 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1309 if (receiveInfo == NULL) {
1310 return 0;
1311 }
1312 for (WebRtc_UWord32 i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001313 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001314 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
1315 _clock.GetTimeInMS()) == 0) {
1316 num++;
1317 }
1318 }
1319 receiveInfoIt++;
1320 }
1321 } else {
1322 while (receiveInfoIt != _receivedInfoMap.end()) {
1323 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1324 if(receiveInfo == NULL) {
1325 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
1326 "%s failed to get RTCPReceiveInformation",
1327 __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +00001328 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001329 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001330 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001331 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001332 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001333 }
1334 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001335}
1336
1337WebRtc_Word32
1338RTCPReceiver::SetPacketTimeout(const WebRtc_UWord32 timeoutMS)
1339{
1340 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1341 _packetTimeOutMS = timeoutMS;
1342 return 0;
1343}
1344
1345void RTCPReceiver::PacketTimeout()
1346{
1347 if(_packetTimeOutMS == 0)
1348 {
1349 // not configured
1350 return;
1351 }
1352
1353 bool packetTimeOut = false;
1354 {
1355 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1356 if(_lastReceived == 0)
1357 {
1358 // not active
1359 return;
1360 }
1361
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001362 WebRtc_UWord32 now = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +00001363
1364 if(now - _lastReceived > _packetTimeOutMS)
1365 {
1366 packetTimeOut = true;
1367 _lastReceived = 0; // only one callback
1368 }
1369 }
1370 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1371 if(packetTimeOut && _cbRtcpFeedback)
1372 {
1373 _cbRtcpFeedback->OnRTCPPacketTimeout(_id);
1374 }
1375}
1376} // namespace webrtc