blob: f7d08f0d42792dc4c8d34071d6517ef0e90700ef [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.org0644b1d2011-12-01 15:42:31 +000030RTCPReceiver::RTCPReceiver(const WebRtc_Word32 id,
31 RtpRtcpClock* clock,
32 ModuleRtpRtcpImpl* owner) :
niklase@google.com470e71d2011-07-07 08:21:25 +000033 _id(id),
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000034 _clock(*clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000035 _method(kRtcpOff),
36 _lastReceived(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000037 _rtpRtcp(*owner),
henrike@webrtc.org65573f22011-12-13 19:17:27 +000038 _criticalSectionFeedbacks(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000039 _cbRtcpFeedback(NULL),
40 _cbVideoFeedback(NULL),
henrike@webrtc.org65573f22011-12-13 19:17:27 +000041 _criticalSectionRTCPReceiver(
42 CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000043 _SSRC(0),
44 _remoteSSRC(0),
45 _remoteSenderInfo(),
46 _lastReceivedSRNTPsecs(0),
47 _lastReceivedSRNTPfrac(0),
48 _receivedInfoMap(),
49 _packetTimeOutMS(0)
50{
51 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
52 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
53}
54
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000055RTCPReceiver::~RTCPReceiver() {
56 delete _criticalSectionRTCPReceiver;
57 delete _criticalSectionFeedbacks;
niklase@google.com470e71d2011-07-07 08:21:25 +000058
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000059 while (!_receivedReportBlockMap.empty()) {
60 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::iterator first =
61 _receivedReportBlockMap.begin();
62 delete first->second;
63 _receivedReportBlockMap.erase(first);
64 }
65 while (!_receivedInfoMap.empty()) {
66 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator first =
67 _receivedInfoMap.begin();
68 delete first->second;
69 _receivedInfoMap.erase(first);
70 }
71 while (!_receivedCnameMap.empty()) {
72 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator first =
73 _receivedCnameMap.begin();
74 delete first->second;
75 _receivedCnameMap.erase(first);
76 }
77 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id,
78 "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +000079}
80
81void
82RTCPReceiver::ChangeUniqueId(const WebRtc_Word32 id)
83{
84 _id = id;
85}
86
87RTCPMethod
88RTCPReceiver::Status() const
89{
90 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
91 return _method;
92}
93
94WebRtc_Word32
95RTCPReceiver::SetRTCPStatus(const RTCPMethod method)
96{
97 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
98 _method = method;
99 return 0;
100}
101
102WebRtc_UWord32
103RTCPReceiver::LastReceived()
104{
105 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
106 return _lastReceived;
107}
108
109WebRtc_Word32
110RTCPReceiver::SetRemoteSSRC( const WebRtc_UWord32 ssrc)
111{
112 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
113
114 // new SSRC reset old reports
115 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
116 _lastReceivedSRNTPsecs = 0;
117 _lastReceivedSRNTPfrac = 0;
118
119 _remoteSSRC = ssrc;
120 return 0;
121}
122
123WebRtc_Word32
124RTCPReceiver::RegisterIncomingRTCPCallback(RtcpFeedback* incomingMessagesCallback)
125{
126 CriticalSectionScoped lock(_criticalSectionFeedbacks);
127 _cbRtcpFeedback = incomingMessagesCallback;
128 return 0;
129}
130
131WebRtc_Word32
132RTCPReceiver::RegisterIncomingVideoCallback(RtpVideoFeedback* incomingMessagesCallback)
133{
134 CriticalSectionScoped lock(_criticalSectionFeedbacks);
135 _cbVideoFeedback = incomingMessagesCallback;
136 return 0;
137}
138
139void
140RTCPReceiver::SetSSRC( const WebRtc_UWord32 ssrc)
141{
142 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
143 _SSRC = ssrc;
144}
145
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000146WebRtc_Word32 RTCPReceiver::ResetRTT(const WebRtc_UWord32 remoteSSRC) {
147 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
148 RTCPReportBlockInformation* reportBlock =
149 GetReportBlockInformation(remoteSSRC);
150 if (reportBlock == NULL) {
151 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
152 "\tfailed to GetReportBlockInformation(%u)", remoteSSRC);
153 return -1;
154 }
155 reportBlock->RTT = 0;
156 reportBlock->avgRTT = 0;
157 reportBlock->minRTT = 0;
158 reportBlock->maxRTT = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000159
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000160 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000161}
162
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000163WebRtc_Word32 RTCPReceiver::RTT(const WebRtc_UWord32 remoteSSRC,
164 WebRtc_UWord16* RTT,
165 WebRtc_UWord16* avgRTT,
166 WebRtc_UWord16* minRTT,
167 WebRtc_UWord16* maxRTT) const {
168 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000169
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000170 RTCPReportBlockInformation* reportBlock =
171 GetReportBlockInformation(remoteSSRC);
172
173 if (reportBlock == NULL) {
174 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
175 "\tfailed to GetReportBlockInformation(%u)",
176 remoteSSRC);
177 return -1;
178 }
179 if (RTT) {
180 *RTT = reportBlock->RTT;
181 }
182 if (avgRTT) {
183 *avgRTT = reportBlock->avgRTT;
184 }
185 if (minRTT) {
186 *minRTT = reportBlock->minRTT;
187 }
188 if (maxRTT) {
189 *maxRTT = reportBlock->maxRTT;
190 }
191 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000192}
193
194void
195RTCPReceiver::UpdateLipSync(const WebRtc_Word32 audioVideoOffset) const
196{
197 CriticalSectionScoped lock(_criticalSectionFeedbacks);
198 if(_cbRtcpFeedback)
199 {
200 _cbRtcpFeedback->OnLipSyncUpdate(_id,audioVideoOffset);
201 }
202};
203
204WebRtc_Word32
205RTCPReceiver::NTP(WebRtc_UWord32 *ReceivedNTPsecs,
206 WebRtc_UWord32 *ReceivedNTPfrac,
207 WebRtc_UWord32 *RTCPArrivalTimeSecs,
208 WebRtc_UWord32 *RTCPArrivalTimeFrac) const
209{
210 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
211 if(ReceivedNTPsecs)
212 {
213 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
214 }
215 if(ReceivedNTPfrac)
216 {
217 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
218 }
219 if(RTCPArrivalTimeFrac)
220 {
221 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
222 }
223 if(RTCPArrivalTimeSecs)
224 {
225 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
226 }
227 return 0;
228}
229
230WebRtc_Word32
231RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const
232{
233 if(senderInfo == NULL)
234 {
235 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
236 return -1;
237 }
238 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
239 if(_lastReceivedSRNTPsecs == 0)
240 {
241 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s No received SR", __FUNCTION__);
242 return -1;
243 }
244 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
245 return 0;
246}
247
248// statistics
249// we can get multiple receive reports when we receive the report from a CE
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000250WebRtc_Word32 RTCPReceiver::StatisticsReceived(
251 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000252 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000253 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
254
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000255 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::const_iterator it =
256 _receivedReportBlockMap.begin();
257
258 while (it != _receivedReportBlockMap.end()) {
259 receiveBlocks->push_back(it->second->remoteReceiveBlock);
260 it++;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000261 }
262 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000263}
264
265WebRtc_Word32
266RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
267 RTCPUtility::RTCPParserV2* rtcpParser)
268{
269 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
270
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000271 _lastReceived = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000272
273 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
274 while (pktType != RTCPUtility::kRtcpNotValidCode)
275 {
276 // Each "case" is responsible for iterate the parser to the
277 // next top level packet.
278 switch (pktType)
279 {
280 case RTCPUtility::kRtcpSrCode:
281 case RTCPUtility::kRtcpRrCode:
282 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
283 break;
284 case RTCPUtility::kRtcpSdesCode:
285 HandleSDES(*rtcpParser);
286 break;
287 case RTCPUtility::kRtcpXrVoipMetricCode:
288 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
289 break;
290 case RTCPUtility::kRtcpByeCode:
291 HandleBYE(*rtcpParser);
292 break;
293 case RTCPUtility::kRtcpRtpfbNackCode:
294 HandleNACK(*rtcpParser, rtcpPacketInformation);
295 break;
296 case RTCPUtility::kRtcpRtpfbTmmbrCode:
297 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
298 break;
299 case RTCPUtility::kRtcpRtpfbTmmbnCode:
300 HandleTMMBN(*rtcpParser);
301 break;
302 case RTCPUtility::kRtcpRtpfbSrReqCode:
303 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
304 break;
305 case RTCPUtility::kRtcpPsfbPliCode:
306 HandlePLI(*rtcpParser, rtcpPacketInformation);
307 break;
308 case RTCPUtility::kRtcpPsfbSliCode:
309 HandleSLI(*rtcpParser, rtcpPacketInformation);
310 break;
311 case RTCPUtility::kRtcpPsfbRpsiCode:
312 HandleRPSI(*rtcpParser, rtcpPacketInformation);
313 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000314 case RTCPUtility::kRtcpExtendedIjCode:
315 HandleIJ(*rtcpParser, rtcpPacketInformation);
316 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000317 case RTCPUtility::kRtcpPsfbFirCode:
318 HandleFIR(*rtcpParser, rtcpPacketInformation);
319 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000320 case RTCPUtility::kRtcpPsfbAppCode:
321 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
322 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000323 case RTCPUtility::kRtcpAppCode:
324 // generic application messages
325 HandleAPP(*rtcpParser, rtcpPacketInformation);
326 break;
327 case RTCPUtility::kRtcpAppItemCode:
328 // generic application messages
329 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
330 break;
331 default:
332 rtcpParser->Iterate();
333 break;
334 }
335 pktType = rtcpParser->PacketType();
336 }
337 return 0;
338}
339
340// no need for critsect we have _criticalSectionRTCPReceiver
341void
342RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
343 RTCPPacketInformation& rtcpPacketInformation)
344{
345 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
346 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
347
348 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
349
350 // SR.SenderSSRC
351 // The synchronization source identifier for the originator of this SR packet
352
353 // rtcpPacket.RR.SenderSSRC
354 // The source of the packet sender, same as of SR? or is this a CE?
355
356 const WebRtc_UWord32 remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
357 const WebRtc_UWord8 numberOfReportBlocks = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.NumberOfReportBlocks:rtcpPacket.SR.NumberOfReportBlocks;
358
359 rtcpPacketInformation.remoteSSRC = remoteSSRC;
360
361 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
362 if (!ptrReceiveInfo)
363 {
364 rtcpParser.Iterate();
365 return;
366 }
367
368 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
369 {
370 WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
371 "Received SR(%d). SSRC:0x%x, from SSRC:0x%x, to us %d.", _id, _SSRC, remoteSSRC, (_remoteSSRC == remoteSSRC)?1:0);
372
373 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
374 {
375 // only signal that we have received a SR when we accept one
376 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
377
378 // We will only store the send report from one source, but
379 // we will store all the receive block
380
381 // Save the NTP time of this report
382 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
383 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
384 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
385 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
386 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
387
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000388 _clock.CurrentNTP(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000389 }
390 else
391 {
392 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
393 }
394 } else
395 {
396 WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
397 "Received RR(%d). SSRC:0x%x, from SSRC:0x%x", _id, _SSRC, remoteSSRC);
398
399 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
400 }
401 UpdateReceiveInformation(*ptrReceiveInfo);
402
403 rtcpPacketType = rtcpParser.Iterate();
404
405 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
406 {
407 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC, numberOfReportBlocks);
408 rtcpPacketType = rtcpParser.Iterate();
409 }
410}
411
412// no need for critsect we have _criticalSectionRTCPReceiver
413void
414RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
415 RTCPPacketInformation& rtcpPacketInformation,
416 const WebRtc_UWord32 remoteSSRC,
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000417 const WebRtc_UWord8 numberOfReportBlocks) {
418 // This will be called once per report block in the RTCP packet.
419 // We filter out all report blocks that are not for us.
420 // Each packet has max 31 RR blocks.
421 //
422 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000423
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000424 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
425 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000426
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000427 // Filter out all report blocks that are not for us.
428 if (rtcpPacket.ReportBlockItem.SSRC != _SSRC) {
429 // This block is not for us ignore it.
430 return;
431 }
432
433 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
434 // _criticalSectionRTCPReceiver.
435 _criticalSectionRTCPReceiver->Leave();
436 WebRtc_UWord32 sendTimeMS =
437 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
438 _criticalSectionRTCPReceiver->Enter();
439
440 RTCPReportBlockInformation* reportBlock =
441 CreateReportBlockInformation(remoteSSRC);
442 if (reportBlock == NULL) {
443 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
444 "\tfailed to CreateReportBlockInformation(%u)", remoteSSRC);
445 return;
446 }
447 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
448 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
449 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
450 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
451 reportBlock->remoteReceiveBlock.cumulativeLost =
452 rb.CumulativeNumOfPacketsLost;
453 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
454 rb.ExtendedHighestSequenceNumber;
455 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
456 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
457 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
458
459 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
460 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
461 }
462
463 WebRtc_UWord32 delaySinceLastSendReport =
464 rtcpPacket.ReportBlockItem.DelayLastSR;
465
466 // local NTP time when we received this
467 WebRtc_UWord32 lastReceivedRRNTPsecs = 0;
468 WebRtc_UWord32 lastReceivedRRNTPfrac = 0;
469
470 _clock.CurrentNTP(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
471
472 // time when we received this in MS
473 WebRtc_UWord32 receiveTimeMS = ModuleRTPUtility::ConvertNTPTimeToMS(
474 lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
475
476 // Estimate RTT
477 WebRtc_UWord32 d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
478 d /= 65536;
479 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
480
481 WebRtc_Word32 RTT = 0;
482
483 if (sendTimeMS > 0) {
484 RTT = receiveTimeMS - d - sendTimeMS;
485 if (RTT <= 0) {
486 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000487 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000488 if (RTT > reportBlock->maxRTT) {
489 // store max RTT
490 reportBlock->maxRTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000491 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000492 if (reportBlock->minRTT == 0) {
493 // first RTT
494 reportBlock->minRTT = (WebRtc_UWord16) RTT;
495 } else if (RTT < reportBlock->minRTT) {
496 // Store min RTT
497 reportBlock->minRTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000498 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000499 // store last RTT
500 reportBlock->RTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000501
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000502 // store average RTT
503 if (reportBlock->numAverageCalcs != 0) {
504 float ac = static_cast<float> (reportBlock->numAverageCalcs);
505 float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT)
506 + ((1 / (ac + 1)) * RTT);
507 reportBlock->avgRTT = static_cast<int> (newAverage + 0.5f);
508 } else {
509 // first RTT
510 reportBlock->avgRTT = (WebRtc_UWord16) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000511 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000512 reportBlock->numAverageCalcs++;
513 }
514
515 WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
516 " -> Received report block(%d), from SSRC:0x%x, RTT:%d, loss:%d",
517 _id, remoteSSRC, RTT, rtcpPacket.ReportBlockItem.FractionLost);
518
519 // rtcpPacketInformation
520 rtcpPacketInformation.AddReportInfo(
521 reportBlock->remoteReceiveBlock.fractionLost, (WebRtc_UWord16) RTT,
522 reportBlock->remoteReceiveBlock.extendedHighSeqNum,
523 reportBlock->remoteReceiveBlock.jitter);
niklase@google.com470e71d2011-07-07 08:21:25 +0000524}
525
526RTCPReportBlockInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000527RTCPReceiver::CreateReportBlockInformation(WebRtc_UWord32 remoteSSRC) {
528 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000529
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000530 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::iterator it =
531 _receivedReportBlockMap.find(remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000532
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000533 RTCPReportBlockInformation* ptrReportBlockInfo = NULL;
534 if (it != _receivedReportBlockMap.end()) {
535 ptrReportBlockInfo = it->second;
536 } else {
537 ptrReportBlockInfo = new RTCPReportBlockInformation;
538 _receivedReportBlockMap[remoteSSRC] = ptrReportBlockInfo;
539 }
540 return ptrReportBlockInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000541}
542
543RTCPReportBlockInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000544RTCPReceiver::GetReportBlockInformation(WebRtc_UWord32 remoteSSRC) const {
545 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000546
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000547 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::const_iterator it =
548 _receivedReportBlockMap.find(remoteSSRC);
549
550 if (it == _receivedReportBlockMap.end()) {
551 return NULL;
552 }
553 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000554}
555
556RTCPCnameInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000557RTCPReceiver::CreateCnameInformation(WebRtc_UWord32 remoteSSRC) {
558 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000559
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000560 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator it =
561 _receivedCnameMap.find(remoteSSRC);
562
563 if (it != _receivedCnameMap.end()) {
564 return it->second;
565 }
566 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000567 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000568 _receivedCnameMap[remoteSSRC] = cnameInfo;
569 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000570}
571
572RTCPCnameInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000573RTCPReceiver::GetCnameInformation(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, RTCPCnameInformation*>::const_iterator it =
577 _receivedCnameMap.find(remoteSSRC);
578
579 if (it == _receivedCnameMap.end()) {
580 return NULL;
581 }
582 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000583}
584
585RTCPReceiveInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000586RTCPReceiver::CreateReceiveInformation(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, RTCPReceiveInformation*>::iterator it =
590 _receivedInfoMap.find(remoteSSRC);
591
592 if (it != _receivedInfoMap.end()) {
593 return it->second;
594 }
595 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
596 _receivedInfoMap[remoteSSRC] = receiveInfo;
597 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000598}
599
600RTCPReceiveInformation*
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000601RTCPReceiver::GetReceiveInformation(WebRtc_UWord32 remoteSSRC) {
602 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000603
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000604 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator it =
605 _receivedInfoMap.find(remoteSSRC);
606 if (it == _receivedInfoMap.end()) {
607 return NULL;
608 }
609 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000610}
611
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000612void RTCPReceiver::UpdateReceiveInformation(
613 RTCPReceiveInformation& receiveInformation) {
614 // Update that this remote is alive
615 receiveInformation.lastTimeReceived = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000616}
617
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000618bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
619 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000620
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000621 bool updateBoundingSet = false;
622 WebRtc_UWord32 timeNow = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000623
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000624 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator receiveInfoIt =
625 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000626
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000627 while (receiveInfoIt != _receivedInfoMap.end()) {
628 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
629 if (receiveInfo == NULL) {
630 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000631 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000632 // time since last received rtcp packet
633 // when we dont have a lastTimeReceived and the object is marked
634 // readyForDelete it's removed from the map
635 if (receiveInfo->lastTimeReceived) {
636 /// use audio define since we don't know what interval the remote peer is
637 // using
638 if ((timeNow - receiveInfo->lastTimeReceived) >
639 5 * RTCP_INTERVAL_AUDIO_MS) {
640 // no rtcp packet for the last five regular intervals, reset limitations
641 receiveInfo->TmmbrSet.lengthOfSet = 0;
642 // prevent that we call this over and over again
643 receiveInfo->lastTimeReceived = 0;
644 // send new TMMBN to all channels using the default codec
645 updateBoundingSet = true;
646 }
647 receiveInfoIt++;
648 } else if (receiveInfo->readyForDelete) {
649 // store our current receiveInfoItem
650 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator
651 receiveInfoItemToBeErased = receiveInfoIt;
652 receiveInfoIt++;
653 delete receiveInfoItemToBeErased->second;
654 _receivedInfoMap.erase(receiveInfoItemToBeErased);
655 } else {
656 receiveInfoIt++;
657 }
658 }
659 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000660}
661
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000662WebRtc_Word32 RTCPReceiver::BoundingSet(bool &tmmbrOwner,
663 TMMBRSet*& boundingSetRec) {
664 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000665
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000666 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator receiveInfoIt =
667 _receivedInfoMap.find(_remoteSSRC);
668
669 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000670 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000671 }
672 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
673 if (receiveInfo == NULL) {
674 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
675 "%s failed to get RTCPReceiveInformation",
676 __FUNCTION__);
677 return -1;
678 }
679 if (receiveInfo->TmmbnBoundingSet.lengthOfSet > 0) {
680 boundingSetRec->VerifyAndAllocateSet(
681 receiveInfo->TmmbnBoundingSet.lengthOfSet + 1);
682 for(WebRtc_UWord32 i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet; i++) {
683 if(receiveInfo->TmmbnBoundingSet.ptrSsrcSet[i] == _SSRC) {
684 // owner of bounding set
685 tmmbrOwner = true;
686 }
687 boundingSetRec->ptrTmmbrSet[i] =
688 receiveInfo->TmmbnBoundingSet.ptrTmmbrSet[i];
689 boundingSetRec->ptrPacketOHSet[i] =
690 receiveInfo->TmmbnBoundingSet.ptrPacketOHSet[i];
691 boundingSetRec->ptrSsrcSet[i] =
692 receiveInfo->TmmbnBoundingSet.ptrSsrcSet[i];
693 }
694 }
695 return receiveInfo->TmmbnBoundingSet.lengthOfSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000696}
697
698// no need for critsect we have _criticalSectionRTCPReceiver
699void
700RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser)
701{
702 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
703 while (pktType == RTCPUtility::kRtcpSdesChunkCode)
704 {
705 HandleSDESChunk(rtcpParser);
706 pktType = rtcpParser.Iterate();
707 }
708}
709
710// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000711void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
712 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
713 RTCPCnameInformation* cnameInfo =
714 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
715 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000716
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000717 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
718 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000719}
720
721// no need for critsect we have _criticalSectionRTCPReceiver
722void
723RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
724 RTCPPacketInformation& rtcpPacketInformation)
725{
726 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
727
728 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.NACK.SenderSSRC);
729 if (ptrReceiveInfo == NULL)
730 {
731 // This remote SSRC must be saved before.
732 rtcpParser.Iterate();
733 return;
734 }
735 if (_SSRC != rtcpPacket.NACK.MediaSSRC)
736 {
737 // Not to us.
738 rtcpParser.Iterate();
739 return;
740 }
741
742 rtcpPacketInformation.ResetNACKPacketIdArray();
743
744 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
745 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode)
746 {
747 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
748 pktType = rtcpParser.Iterate();
749 }
750}
751
752// no need for critsect we have _criticalSectionRTCPReceiver
753void
754RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
755 RTCPPacketInformation& rtcpPacketInformation)
756{
757 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
758
759 WebRtc_UWord16 bitMask = rtcpPacket.NACKItem.BitMask;
760 if(bitMask)
761 {
762 for(int i=1; i <= 16; ++i)
763 {
764 if(bitMask & 0x01)
765 {
766 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
767 }
768 bitMask = bitMask >>1;
769 }
770 }
771
772 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
773}
774
775// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000776void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
777 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000778
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000779 // clear our lists
780 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
781 std::map<WebRtc_UWord32, RTCPReportBlockInformation*>::iterator
782 reportBlockInfoIt = _receivedReportBlockMap.find(
783 rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000784
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000785 if (reportBlockInfoIt != _receivedReportBlockMap.end()) {
786 delete reportBlockInfoIt->second;
787 _receivedReportBlockMap.erase(reportBlockInfoIt);
788 }
789 // we can't delete it due to TMMBR
790 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::iterator receiveInfoIt =
791 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000792
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000793 if (receiveInfoIt != _receivedInfoMap.end()) {
794 receiveInfoIt->second->readyForDelete = true;
795 }
796
797 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator cnameInfoIt =
798 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
799
800 if (cnameInfoIt != _receivedCnameMap.end()) {
801 delete cnameInfoIt->second;
802 _receivedCnameMap.erase(cnameInfoIt);
803 }
804 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000805}
806
807// no need for critsect we have _criticalSectionRTCPReceiver
808void
809RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
810 RTCPPacketInformation& rtcpPacketInformation)
811{
812 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
813
814 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
815
816 if(rtcpPacket.XRVOIPMetricItem.SSRC == _SSRC)
817 {
818 // Store VoIP metrics block if it's about me
819 // from OriginatorSSRC do we filter it?
820 // rtcpPacket.XR.OriginatorSSRC;
821
822 RTCPVoIPMetric receivedVoIPMetrics;
823 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
824 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
825 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
826 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
827 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
828 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
829 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
830 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
831 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
832 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
833 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
834 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
835 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
836 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
837 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
838 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
839 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
840 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
841 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
842 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
843
844 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
845
846 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
847 }
848 rtcpParser.Iterate();
849}
850
851// no need for critsect we have _criticalSectionRTCPReceiver
852void
853RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
854 RTCPPacketInformation& rtcpPacketInformation)
855{
856 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
857
858 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.PLI.SenderSSRC);
859 if (ptrReceiveInfo == NULL)
860 {
861 // This remote SSRC must be saved before.
862 rtcpParser.Iterate();
863 return;
864 }
865 if (_SSRC != rtcpPacket.PLI.MediaSSRC)
866 {
867 // Not to us.
868 rtcpParser.Iterate();
869 return;
870 }
871 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli; // received signal that we need to send a new key frame
872 rtcpParser.Iterate();
873}
874
875// no need for critsect we have _criticalSectionRTCPReceiver
876void
877RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
878 RTCPPacketInformation& rtcpPacketInformation)
879{
880 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
881
882 WebRtc_UWord32 senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
883 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
884 if (ptrReceiveInfo == NULL)
885 {
886 // This remote SSRC must be saved before.
887 rtcpParser.Iterate();
888 return;
889 }
890 if(rtcpPacket.TMMBR.MediaSSRC)
891 {
892 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
893 // in relay mode this is a valid number
894 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
895 }
896
897 // Use packet length to calc max number of TMMBR blocks
898 // each TMMBR block is 8 bytes
899 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
900
901 // sanity
902 if(maxNumOfTMMBRBlocks > 200) // we can't have more than what's in one packet
903 {
904 assert(false);
905 rtcpParser.Iterate();
906 return;
907 }
908 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((WebRtc_UWord32)maxNumOfTMMBRBlocks);
909
910 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
911 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode)
912 {
913 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
914 pktType = rtcpParser.Iterate();
915 }
916}
917
918// no need for critsect we have _criticalSectionRTCPReceiver
919void
920RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
921 const RTCPUtility::RTCPPacket& rtcpPacket,
922 RTCPPacketInformation& rtcpPacketInformation,
923 const WebRtc_UWord32 senderSSRC)
924{
925 if (_SSRC == rtcpPacket.TMMBRItem.SSRC &&
926 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
927 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000928 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
929 _clock.GetTimeInMS());
niklase@google.com470e71d2011-07-07 08:21:25 +0000930 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
931 }
932}
933
934// no need for critsect we have _criticalSectionRTCPReceiver
935void
936RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser)
937{
938 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
939 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.TMMBN.SenderSSRC);
940 if (ptrReceiveInfo == NULL)
941 {
942 // This remote SSRC must be saved before.
943 rtcpParser.Iterate();
944 return;
945 }
946 // Use packet length to calc max number of TMMBN blocks
947 // each TMMBN block is 8 bytes
948 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
949
950 // sanity
951 if(maxNumOfTMMBNBlocks > 200) // we cant have more than what's in one packet
952 {
953 assert(false);
954 rtcpParser.Iterate();
955 return;
956 }
957
958 ptrReceiveInfo->VerifyAndAllocateBoundingSet((WebRtc_UWord32)maxNumOfTMMBNBlocks);
959
960 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
961 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode)
962 {
963 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
964 pktType = rtcpParser.Iterate();
965 }
966}
967
968// no need for critsect we have _criticalSectionRTCPReceiver
969void
970RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
971 RTCPPacketInformation& rtcpPacketInformation)
972{
973 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
974 rtcpParser.Iterate();
975}
976
977// no need for critsect we have _criticalSectionRTCPReceiver
978void
979RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
980 const RTCPUtility::RTCPPacket& rtcpPacket)
981{
982 const unsigned int idx = receiveInfo.TmmbnBoundingSet.lengthOfSet;
983
984 receiveInfo.TmmbnBoundingSet.ptrTmmbrSet[idx] = rtcpPacket.TMMBNItem.MaxTotalMediaBitRate;
985 receiveInfo.TmmbnBoundingSet.ptrPacketOHSet[idx] = rtcpPacket.TMMBNItem.MeasuredOverhead;
986 receiveInfo.TmmbnBoundingSet.ptrSsrcSet[idx] = rtcpPacket.TMMBNItem.SSRC;
987
988 ++receiveInfo.TmmbnBoundingSet.lengthOfSet;
989}
990
991// no need for critsect we have _criticalSectionRTCPReceiver
992void
993RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
994 RTCPPacketInformation& rtcpPacketInformation)
995{
996 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
997
998 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.SLI.SenderSSRC);
999 if (ptrReceiveInfo == NULL)
1000 {
1001 // This remote SSRC must be saved before.
1002 rtcpParser.Iterate();
1003 return;
1004 }
1005
1006 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1007 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode)
1008 {
1009 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1010 pktType = rtcpParser.Iterate();
1011 }
1012}
1013
1014// no need for critsect we have _criticalSectionRTCPReceiver
1015void
1016RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1017 RTCPPacketInformation& rtcpPacketInformation)
1018{
1019 // in theory there could be multiple slices lost
1020 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1021 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
1022}
1023
1024void
1025RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1026 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1027{
1028 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1029
1030 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.RPSI.SenderSSRC);
1031 if (ptrReceiveInfo == NULL)
1032 {
1033 // This remote SSRC must be saved before.
1034 rtcpParser.Iterate();
1035 return;
1036 }
1037 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1038 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1039 {
1040 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1041 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1042 {
1043 // to us unknown
1044 // continue
1045 rtcpParser.Iterate();
1046 return;
1047 }
1048 rtcpPacketInformation.rpsiPictureId = 0;
1049
1050 // convert NativeBitString to rpsiPictureId
1051 WebRtc_UWord8 numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1052 for(WebRtc_UWord8 n = 0; n < (numberOfBytes-1); n++)
1053 {
1054 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1055 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1056 }
1057 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1058 }
1059}
1060
1061// no need for critsect we have _criticalSectionRTCPReceiver
1062void
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001063RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1064 RTCPPacketInformation& rtcpPacketInformation)
1065{
1066 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1067 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode)
1068 {
1069 HandleREMBItem(rtcpParser, rtcpPacketInformation);
asapersson@webrtc.orgc5a1cee2012-01-10 12:54:44 +00001070 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001071 }
1072}
1073
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001074// no need for critsect we have _criticalSectionRTCPReceiver
1075void
1076RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1077 RTCPPacketInformation& rtcpPacketInformation)
1078{
1079 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1080
1081 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1082 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode)
1083 {
1084 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1085 pktType = rtcpParser.Iterate();
1086 }
1087}
1088
1089void
1090RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1091 RTCPPacketInformation& rtcpPacketInformation)
1092{
1093 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1094 rtcpPacketInformation.interArrivalJitter =
1095 rtcpPacket.ExtendedJitterReportItem.Jitter;
1096}
1097
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001098void
1099RTCPReceiver::HandleREMBItem(RTCPUtility::RTCPParserV2& rtcpParser,
1100 RTCPPacketInformation& rtcpPacketInformation)
1101{
1102 rtcpParser.Iterate();
1103 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1104
1105 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1106 rtcpPacketInformation.receiverEstimatedMaxBitrate = rtcpPacket.REMB.BitRate;
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00001107 // TODO(pwestin) send up SSRCs and do a sanity check
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001108}
1109
1110// no need for critsect we have _criticalSectionRTCPReceiver
1111void
niklase@google.com470e71d2011-07-07 08:21:25 +00001112RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1113 RTCPPacketInformation& rtcpPacketInformation)
1114{
1115 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1116
1117 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
1118 if (ptrReceiveInfo == NULL)
1119 {
1120 // This remote SSRC must be saved before.
1121 rtcpParser.Iterate();
1122 return;
1123 }
1124
1125 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1126 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode)
1127 {
1128 HandleFIRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1129 pktType = rtcpParser.Iterate();
1130 }
1131}
1132
1133// no need for critsect we have _criticalSectionRTCPReceiver
1134void
1135RTCPReceiver::HandleFIRItem(RTCPReceiveInformation& receiveInfo,
1136 const RTCPUtility::RTCPPacket& rtcpPacket,
1137 RTCPPacketInformation& rtcpPacketInformation)
1138{
1139 if (_SSRC == rtcpPacket.FIRItem.SSRC) // is it our sender that is requested to generate a new keyframe
1140 {
1141 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1142 // we don't know who this originate from
1143
1144 // check if we have reported this FIRSequenceNumber before
1145 if (rtcpPacket.FIRItem.CommandSequenceNumber != receiveInfo.lastFIRSequenceNumber)
1146 {
1147 //
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001148 WebRtc_UWord32 now = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +00001149
1150 // extra sanity don't go crazy with the callbacks
1151 if( (now - receiveInfo.lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS)
1152 {
1153 receiveInfo.lastFIRRequest = now;
1154 receiveInfo.lastFIRSequenceNumber = rtcpPacket.FIRItem.CommandSequenceNumber;
1155
1156 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir; // received signal that we need to send a new key frame
1157 }
1158 }
1159 }
1160}
1161
1162void
1163RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1164 RTCPPacketInformation& rtcpPacketInformation)
1165{
1166 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1167
1168 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1169 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1170 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
1171
1172 rtcpParser.Iterate();
1173}
1174
1175void
1176RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1177 RTCPPacketInformation& rtcpPacketInformation)
1178{
1179 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1180
1181 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
1182
1183 rtcpParser.Iterate();
1184}
1185
1186void
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00001187RTCPReceiver::OnReceivedIntraFrameRequest(const FrameType frameType,
1188 const WebRtc_UWord8 streamIdx) const
niklase@google.com470e71d2011-07-07 08:21:25 +00001189{
1190 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1191
1192 if(_cbVideoFeedback)
1193 {
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00001194 _cbVideoFeedback->OnReceivedIntraFrameRequest(_id, frameType, streamIdx);
niklase@google.com470e71d2011-07-07 08:21:25 +00001195 }
1196}
1197
1198void
1199RTCPReceiver::OnReceivedSliceLossIndication(const WebRtc_UWord8 pitureID) const
1200{
1201 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1202
1203 if(_cbRtcpFeedback)
1204 {
1205 _cbRtcpFeedback->OnSLIReceived(_id, pitureID);
1206 }
1207}
1208
1209void
1210RTCPReceiver::OnReceivedReferencePictureSelectionIndication(const WebRtc_UWord64 pitureID) const
1211{
1212 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1213
1214 if(_cbRtcpFeedback)
1215 {
1216 _cbRtcpFeedback->OnRPSIReceived(_id, pitureID);
1217 }
1218}
1219
1220// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001221void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
1222 RTCPPacketInformation& rtcpPacketInformation)
niklase@google.com470e71d2011-07-07 08:21:25 +00001223{
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001224 // Process TMMBR and REMB first to avoid multiple callbacks
1225 // to OnNetworkChanged.
1226 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr)
1227 {
1228 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1229 "SIG [RTCP] Incoming TMMBR to id:%d", _id);
1230
1231 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1232 _rtpRtcp.OnReceivedTMMBR();
1233 }
1234 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb)
1235 {
1236 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1237 "SIG [RTCP] Incoming REMB to id:%d", _id);
1238
1239 // We need to bounce this to the default channel.
1240 _rtpRtcp.OnReceivedEstimatedMaxBitrate(
1241 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1242 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001243 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1244 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr)
1245 {
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001246 if (rtcpPacketInformation.reportBlock)
niklase@google.com470e71d2011-07-07 08:21:25 +00001247 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001248 _rtpRtcp.OnPacketLossStatisticsUpdate(
1249 rtcpPacketInformation.fractionLost,
1250 rtcpPacketInformation.roundTripTime,
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001251 rtcpPacketInformation.lastReceivedExtendedHighSeqNum);
niklase@google.com470e71d2011-07-07 08:21:25 +00001252 }
1253 }
1254 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr)
1255 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001256 _rtpRtcp.OnReceivedNTP();
niklase@google.com470e71d2011-07-07 08:21:25 +00001257 }
1258 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq)
1259 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001260 _rtpRtcp.OnRequestSendReport();
niklase@google.com470e71d2011-07-07 08:21:25 +00001261 }
1262 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack)
1263 {
1264 if (rtcpPacketInformation.nackSequenceNumbersLength > 0)
1265 {
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001266 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1267 "SIG [RTCP] Incoming NACK to id:%d", _id);
1268 _rtpRtcp.OnReceivedNACK(
1269 rtcpPacketInformation.nackSequenceNumbersLength,
1270 rtcpPacketInformation.nackSequenceNumbers);
niklase@google.com470e71d2011-07-07 08:21:25 +00001271 }
1272 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001273 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1274 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir))
1275 {
1276 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli)
1277 {
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001278 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1279 "SIG [RTCP] Incoming PLI to id:%d", _id);
1280 } else
niklase@google.com470e71d2011-07-07 08:21:25 +00001281 {
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001282 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1283 "SIG [RTCP] Incoming FIR to id:%d", _id);
niklase@google.com470e71d2011-07-07 08:21:25 +00001284 }
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00001285 _rtpRtcp.OnReceivedIntraFrameRequest(&_rtpRtcp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001286 }
1287 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli)
1288 {
1289 // we need use a bounce it up to handle default channel
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00001290 _rtpRtcp.OnReceivedSliceLossIndication(
1291 rtcpPacketInformation.sliPictureId);
1292 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001293 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi)
1294 {
1295 // we need use a bounce it up to handle default channel
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001296 _rtpRtcp.OnReceivedReferencePictureSelectionIndication(
1297 rtcpPacketInformation.rpsiPictureId);
niklase@google.com470e71d2011-07-07 08:21:25 +00001298 }
1299 {
1300 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1301
1302 // we need a feedback that we have received a report block(s) so that we can generate a new packet
1303 // in a conference relay scenario, one received report can generate several RTCP packets, based
1304 // on number relayed/mixed
1305 // a send report block should go out to all receivers
1306 if(_cbRtcpFeedback)
1307 {
1308 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr)
1309 {
1310 _cbRtcpFeedback->OnSendReportReceived(_id, rtcpPacketInformation.remoteSSRC);
1311 } else
1312 {
1313 _cbRtcpFeedback->OnReceiveReportReceived(_id, rtcpPacketInformation.remoteSSRC);
1314 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001315 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb)
1316 {
1317 _cbRtcpFeedback->OnReceiverEstimatedMaxBitrateReceived(_id,
1318 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1319 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001320 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1321 {
1322 WebRtc_Word8 VoIPmetricBuffer[7*4];
1323 VoIPmetricBuffer[0] = rtcpPacketInformation.VoIPMetric->lossRate;
1324 VoIPmetricBuffer[1] = rtcpPacketInformation.VoIPMetric->discardRate;
1325 VoIPmetricBuffer[2] = rtcpPacketInformation.VoIPMetric->burstDensity;
1326 VoIPmetricBuffer[3] = rtcpPacketInformation.VoIPMetric->gapDensity;
1327
1328 VoIPmetricBuffer[4] = (WebRtc_UWord8)(rtcpPacketInformation.VoIPMetric->burstDuration >> 8);
1329 VoIPmetricBuffer[5] = (WebRtc_UWord8)(rtcpPacketInformation.VoIPMetric->burstDuration);
1330 VoIPmetricBuffer[6] = (WebRtc_UWord8)(rtcpPacketInformation.VoIPMetric->gapDuration >> 8);
1331 VoIPmetricBuffer[7] = (WebRtc_UWord8)(rtcpPacketInformation.VoIPMetric->gapDuration);
1332
1333 VoIPmetricBuffer[8] = (WebRtc_UWord8)(rtcpPacketInformation.VoIPMetric->roundTripDelay >> 8);
1334 VoIPmetricBuffer[9] = (WebRtc_UWord8)(rtcpPacketInformation.VoIPMetric->roundTripDelay);
1335 VoIPmetricBuffer[10] = (WebRtc_UWord8)(rtcpPacketInformation.VoIPMetric->endSystemDelay >> 8);
1336 VoIPmetricBuffer[11] = (WebRtc_UWord8)(rtcpPacketInformation.VoIPMetric->endSystemDelay);
1337
1338 VoIPmetricBuffer[12] = rtcpPacketInformation.VoIPMetric->signalLevel;
1339 VoIPmetricBuffer[13] = rtcpPacketInformation.VoIPMetric->noiseLevel;
1340 VoIPmetricBuffer[14] = rtcpPacketInformation.VoIPMetric->RERL;
1341 VoIPmetricBuffer[15] = rtcpPacketInformation.VoIPMetric->Gmin;
1342
1343 VoIPmetricBuffer[16] = rtcpPacketInformation.VoIPMetric->Rfactor;
1344 VoIPmetricBuffer[17] = rtcpPacketInformation.VoIPMetric->extRfactor;
1345 VoIPmetricBuffer[18] = rtcpPacketInformation.VoIPMetric->MOSLQ;
1346 VoIPmetricBuffer[19] = rtcpPacketInformation.VoIPMetric->MOSCQ;
1347
1348 VoIPmetricBuffer[20] = rtcpPacketInformation.VoIPMetric->RXconfig;
1349 VoIPmetricBuffer[21] = 0; // reserved
1350 VoIPmetricBuffer[22] = (WebRtc_UWord8)(rtcpPacketInformation.VoIPMetric->JBnominal >> 8);
1351 VoIPmetricBuffer[23] = (WebRtc_UWord8)(rtcpPacketInformation.VoIPMetric->JBnominal);
1352
1353 VoIPmetricBuffer[24] = (WebRtc_UWord8)(rtcpPacketInformation.VoIPMetric->JBmax >> 8);
1354 VoIPmetricBuffer[25] = (WebRtc_UWord8)(rtcpPacketInformation.VoIPMetric->JBmax);
1355 VoIPmetricBuffer[26] = (WebRtc_UWord8)(rtcpPacketInformation.VoIPMetric->JBabsMax >> 8);
1356 VoIPmetricBuffer[27] = (WebRtc_UWord8)(rtcpPacketInformation.VoIPMetric->JBabsMax);
1357
1358 _cbRtcpFeedback->OnXRVoIPMetricReceived(_id, rtcpPacketInformation.VoIPMetric, VoIPmetricBuffer);
1359 }
1360 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpApp)
1361 {
1362 _cbRtcpFeedback->OnApplicationDataReceived(_id,
1363 rtcpPacketInformation.applicationSubType,
1364 rtcpPacketInformation.applicationName,
1365 rtcpPacketInformation.applicationLength,
1366 rtcpPacketInformation.applicationData);
1367 }
1368 }
1369 }
1370}
1371
1372void
1373RTCPReceiver::UpdateBandwidthEstimate(const WebRtc_UWord16 bwEstimateKbit)
1374{
1375 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1376
1377 if(_cbRtcpFeedback)
1378 {
1379 _cbRtcpFeedback->OnTMMBRReceived(_id, bwEstimateKbit);
1380 }
1381
1382}
1383
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001384WebRtc_Word32 RTCPReceiver::CNAME(const WebRtc_UWord32 remoteSSRC,
1385 char cName[RTCP_CNAME_SIZE]) const {
1386 if (cName == NULL) {
1387 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
1388 "%s invalid argument", __FUNCTION__);
1389 return -1;
1390 }
1391 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1392 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
1393 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +00001394
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001395 cName[RTCP_CNAME_SIZE - 1] = 0;
1396 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1397 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001398}
1399
1400// no callbacks allowed inside this function
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001401WebRtc_Word32 RTCPReceiver::TMMBRReceived(const WebRtc_UWord32 size,
1402 const WebRtc_UWord32 accNumCandidates,
1403 TMMBRSet* candidateSet) const {
1404 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001405
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001406 std::map<WebRtc_UWord32, RTCPReceiveInformation*>::const_iterator
1407 receiveInfoIt = _receivedInfoMap.begin();
1408 if (receiveInfoIt == _receivedInfoMap.end()) {
1409 return -1;
1410 }
1411 WebRtc_UWord32 num = accNumCandidates;
1412 if (candidateSet) {
1413 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1414 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1415 if (receiveInfo == NULL) {
1416 return 0;
1417 }
1418 for (WebRtc_UWord32 i = 0;
1419 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet); i++) {
1420 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
1421 _clock.GetTimeInMS()) == 0) {
1422 num++;
1423 }
1424 }
1425 receiveInfoIt++;
1426 }
1427 } else {
1428 while (receiveInfoIt != _receivedInfoMap.end()) {
1429 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1430 if(receiveInfo == NULL) {
1431 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
1432 "%s failed to get RTCPReceiveInformation",
1433 __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +00001434 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001435 }
1436 num += receiveInfo->TmmbrSet.lengthOfSet;
1437 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001438 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001439 }
1440 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001441}
1442
1443WebRtc_Word32
1444RTCPReceiver::SetPacketTimeout(const WebRtc_UWord32 timeoutMS)
1445{
1446 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1447 _packetTimeOutMS = timeoutMS;
1448 return 0;
1449}
1450
1451void RTCPReceiver::PacketTimeout()
1452{
1453 if(_packetTimeOutMS == 0)
1454 {
1455 // not configured
1456 return;
1457 }
1458
1459 bool packetTimeOut = false;
1460 {
1461 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1462 if(_lastReceived == 0)
1463 {
1464 // not active
1465 return;
1466 }
1467
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001468 WebRtc_UWord32 now = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +00001469
1470 if(now - _lastReceived > _packetTimeOutMS)
1471 {
1472 packetTimeOut = true;
1473 _lastReceived = 0; // only one callback
1474 }
1475 }
1476 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1477 if(packetTimeOut && _cbRtcpFeedback)
1478 {
1479 _cbRtcpFeedback->OnRTCPPacketTimeout(_id);
1480 }
1481}
1482} // namespace webrtc