blob: 89af2879b1a3cd4d07d67478caffc832d1339cc7 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
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_sender.h"
12#include "rtcp_utility.h"
13
14#include <string.h> // memcpy
15#include <cassert> // assert
16#include <cstdlib> // rand
17
18#include "trace.h"
19#include "tick_util.h"
20#include "common_types.h"
21#include "critical_section_wrapper.h"
22
23namespace webrtc {
24RTCPSender::RTCPSender(const WebRtc_Word32 id,
25 const bool audio,
26 ModuleRtpRtcpPrivate& callback) :
27 _id(id),
28 _audio(audio),
29 _method(kRtcpOff),
30 _cbRtcpPrivate(callback),
31 _criticalSectionTransport(*CriticalSectionWrapper::CreateCriticalSection()),
32 _cbTransport(NULL),
33
34 _criticalSectionRTCPSender(*CriticalSectionWrapper::CreateCriticalSection()),
35 _usingNack(false),
36 _sending(false),
37 _sendTMMBN(false),
38 _TMMBR(false),
39 _nextTimeToSendRTCP(0),
40 _SSRC(0),
41 _remoteSSRC(0),
42 _CNAME(),
43 _reportBlocks(),
44 _csrcCNAMEs(),
45
46 _cameraDelayMS(0),
47
48 _lastSendReport(),
49 _lastRTCPTime(),
50
51 _CSRCs(0),
52 _CSRC(),
53 _includeCSRCs(true),
54
55 _sequenceNumberFIR(0),
56 _lastTimeFIR(0),
57
58 _tmmbrHelp(audio),
59 _tmmbr_Send(0),
60 _packetOH_Send(0),
61 _remoteRateControl(),
62
63 _appSend(false),
64 _appSubType(0),
65 _appName(),
66 _appData(NULL),
67 _appLength(0),
68 _xrSendVoIPMetric(false),
69 _xrVoIPMetric()
70{
71 memset(_CNAME, 0, sizeof(_CNAME));
72 memset(_lastSendReport, 0, sizeof(_lastSendReport));
73 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
74
75 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
76}
77
78RTCPSender::~RTCPSender()
79{
80 if(_appData)
81 {
82 delete [] _appData;
83 }
84
85 MapItem* item = _reportBlocks.First();
86 while(item)
87 {
88 RTCPReportBlock* ptr = (RTCPReportBlock*)(item->GetItem());
89 if(ptr)
90 {
91 delete ptr;
92 }
93 _reportBlocks.Erase(item);
94 item = _reportBlocks.First();
95 }
96 item = _csrcCNAMEs.First();
97 while(item)
98 {
99 RTCPUtility::RTCPCnameInformation* ptr = (RTCPUtility::RTCPCnameInformation*)(item->GetItem());
100 if(ptr)
101 {
102 delete ptr;
103 }
104 _csrcCNAMEs.Erase(item);
105 item = _csrcCNAMEs.First();
106 }
107 delete &_criticalSectionTransport;
108 delete &_criticalSectionRTCPSender;
109
110 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
111}
112
113WebRtc_Word32
114RTCPSender::Init()
115{
116 CriticalSectionScoped lock(_criticalSectionRTCPSender);
117
118 _method = kRtcpOff;
119 _cbTransport = NULL;
120 _usingNack = false;
121 _sending = false;
122 _sendTMMBN = false;
123 _TMMBR = false;
124 _SSRC = 0;
125 _remoteSSRC = 0;
126 _cameraDelayMS = 0;
127 _sequenceNumberFIR = 0;
128 _tmmbr_Send = 0;
129 _packetOH_Send = 0;
130 _remoteRateControl.Reset();
131 _nextTimeToSendRTCP = 0;
132 _CSRCs = 0;
133 _appSend = false;
134 _appSubType = 0;
135
136 if(_appData)
137 {
138 delete [] _appData;
139 _appData = NULL;
140 }
141 _appLength = 0;
142
143 _xrSendVoIPMetric = false;
144
145 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
146 memset(_CNAME, 0, sizeof(_CNAME));
147 memset(_lastSendReport, 0, sizeof(_lastSendReport));
148 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
149 return 0;
150}
151
152void
153RTCPSender::ChangeUniqueId(const WebRtc_Word32 id)
154{
155 _id = id;
156}
157
158WebRtc_Word32
159RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
160{
161 CriticalSectionScoped lock(_criticalSectionTransport);
162 _cbTransport = outgoingTransport;
163 return 0;
164}
165
166RTCPMethod
167RTCPSender::Status() const
168{
169 CriticalSectionScoped lock(_criticalSectionRTCPSender);
170 return _method;
171}
172
173WebRtc_Word32
174RTCPSender::SetRTCPStatus(const RTCPMethod method)
175{
176 CriticalSectionScoped lock(_criticalSectionRTCPSender);
177 if(method != kRtcpOff)
178 {
179 if(_audio)
180 {
181 _nextTimeToSendRTCP = ModuleRTPUtility::GetTimeInMS() + (RTCP_INTERVAL_AUDIO_MS/2);
182 } else
183 {
184 _nextTimeToSendRTCP = ModuleRTPUtility::GetTimeInMS() + (RTCP_INTERVAL_VIDEO_MS/2);
185 }
186 }
187 _method = method;
188 return 0;
189}
190
191bool
192RTCPSender::Sending() const
193{
194 CriticalSectionScoped lock(_criticalSectionRTCPSender);
195 return _sending;
196}
197
198WebRtc_Word32
199RTCPSender::SetSendingStatus(const bool sending)
200{
201 bool sendRTCPBye = false;
202 {
203 CriticalSectionScoped lock(_criticalSectionRTCPSender);
204
205 if(_method != kRtcpOff)
206 {
207 if(sending == false && _sending == true)
208 {
209 // Trigger RTCP bye
210 sendRTCPBye = true;
211 }
212 }
213 _sending = sending;
214 }
215 if(sendRTCPBye)
216 {
217 return SendRTCP(kRtcpBye);
218 }
219 return 0;
220}
221
222bool
223RTCPSender::TMMBR() const
224{
225 CriticalSectionScoped lock(_criticalSectionRTCPSender);
226 return _TMMBR;
227}
228
229WebRtc_Word32
230RTCPSender::SetTMMBRStatus(const bool enable)
231{
232 CriticalSectionScoped lock(_criticalSectionRTCPSender);
233 _TMMBR = enable;
234 return 0;
235}
236
237void
238RTCPSender::SetSSRC( const WebRtc_UWord32 ssrc)
239{
240 CriticalSectionScoped lock(_criticalSectionRTCPSender);
241
242 if(_SSRC != 0)
243 {
244 // not first SetSSRC, probably due to a collision
245 // schedule a new RTCP report
246 _nextTimeToSendRTCP = ModuleRTPUtility::GetTimeInMS() + 100; // make sure that we send a RTP packet
247 }
248 _SSRC = ssrc;
249}
250
251WebRtc_Word32
252RTCPSender::SetRemoteSSRC( const WebRtc_UWord32 ssrc)
253{
254 CriticalSectionScoped lock(_criticalSectionRTCPSender);
255 _remoteSSRC = ssrc;
256 _remoteRateControl.Reset();
257 return 0;
258}
259
260WebRtc_Word32
261RTCPSender::SetCameraDelay(const WebRtc_Word32 delayMS)
262{
263 CriticalSectionScoped lock(_criticalSectionRTCPSender);
264 if(delayMS > 1000 || delayMS < -1000)
265 {
266 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
267 return -1;
268 }
269 _cameraDelayMS = delayMS;
270 return 0;
271}
272
273WebRtc_Word32
274RTCPSender::CNAME(WebRtc_Word8 cName[RTCP_CNAME_SIZE])
275{
276 if(cName == NULL)
277 {
278 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
279 return -1;
280 }
281 CriticalSectionScoped lock(_criticalSectionRTCPSender);
282 memcpy(cName, _CNAME, RTCP_CNAME_SIZE);
283 return 0;
284}
285
286WebRtc_Word32
287RTCPSender::SetCNAME(const WebRtc_Word8 cName[RTCP_CNAME_SIZE])
288{
289 if(cName == NULL)
290 {
291 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
292 return -1;
293 }
294 WebRtc_Word32 length = (WebRtc_Word32)strlen(cName);
295 if(length > RTCP_CNAME_SIZE)
296 {
297 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, too long cName", __FUNCTION__);
298 return -1;
299 }
300 CriticalSectionScoped lock(_criticalSectionRTCPSender);
301
302 memcpy(_CNAME, cName, length+1);
303 return 0;
304}
305
306WebRtc_Word32
307RTCPSender::AddMixedCNAME(const WebRtc_UWord32 SSRC,
308 const WebRtc_Word8 cName[RTCP_CNAME_SIZE])
309{
310 if(cName == NULL)
311 {
312 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
313 return -1;
314 }
315 WebRtc_Word32 length = (WebRtc_Word32)strlen(cName);
316 if(length > RTCP_CNAME_SIZE)
317 {
318 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, too long cName", __FUNCTION__);
319 return -1;
320 }
321
322 CriticalSectionScoped lock(_criticalSectionRTCPSender);
323 if(_csrcCNAMEs.Size() == kRtpCsrcSize)
324 {
325 return -1;
326 }
327 RTCPUtility::RTCPCnameInformation* ptr= new RTCPUtility::RTCPCnameInformation();
328
329 memcpy(ptr->name, cName, length+1);
330 ptr->length = (WebRtc_UWord8)length;
331 _csrcCNAMEs.Insert(SSRC, ptr);
332 return 0;
333}
334
335WebRtc_Word32
336RTCPSender::RemoveMixedCNAME(const WebRtc_UWord32 SSRC)
337{
338 CriticalSectionScoped lock(_criticalSectionRTCPSender);
339 MapItem* item= _csrcCNAMEs.Find(SSRC);
340 if(item)
341 {
342 RTCPUtility::RTCPCnameInformation* ptr= (RTCPUtility::RTCPCnameInformation*)(item->GetItem());
343 if(ptr)
344 {
345 delete ptr;
346 }
347 _csrcCNAMEs.Erase(item);
348 return 0;
349 }
350 return -1;
351}
352
353bool
354RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
355{
356/*
357 For audio we use a fix 5 sec interval
358
359 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
360 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
361
362
363From RFC 3550
364
365 MAX RTCP BW is 5% if the session BW
366 A send report is approximately 65 bytes inc CNAME
367 A report report is approximately 28 bytes
368
369 The RECOMMENDED value for the reduced minimum in seconds is 360
370 divided by the session bandwidth in kilobits/second. This minimum
371 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
372
373 If the participant has not yet sent an RTCP packet (the variable
374 initial is true), the constant Tmin is set to 2.5 seconds, else it
375 is set to 5 seconds.
376
377 The interval between RTCP packets is varied randomly over the
378 range [0.5,1.5] times the calculated interval to avoid unintended
379 synchronization of all participants
380
381 if we send
382 If the participant is a sender (we_sent true), the constant C is
383 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
384 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
385 number of senders.
386
387 if we receive only
388 If we_sent is not true, the constant C is set
389 to the average RTCP packet size divided by 75% of the RTCP
390 bandwidth. The constant n is set to the number of receivers
391 (members - senders). If the number of senders is greater than
392 25%, senders and receivers are treated together.
393
394 reconsideration NOT required for peer-to-peer
395 "timer reconsideration" is
396 employed. This algorithm implements a simple back-off mechanism
397 which causes users to hold back RTCP packet transmission if the
398 group sizes are increasing.
399
400 n = number of members
401 C = avg_size/(rtcpBW/4)
402
403 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
404
405 4. The calculated interval T is set to a number uniformly distributed
406 between 0.5 and 1.5 times the deterministic calculated interval.
407
408 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
409 for the fact that the timer reconsideration algorithm converges to
410 a value of the RTCP bandwidth below the intended average
411*/
412
413 if(_method == kRtcpOff)
414 {
415 return false;
416 }
417
418 WebRtc_UWord32 now = ModuleRTPUtility::GetTimeInMS();
419
420 CriticalSectionScoped lock(_criticalSectionRTCPSender);
421
422 if(!_audio && sendKeyframeBeforeRTP)
423 {
424 // for video key-frames we want to send the RTCP before the large key-frame
425 // if we have a 100 ms margin
426 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
427 }
428
429 if(now > _nextTimeToSendRTCP)
430 {
431 return true;
432
433 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
434 {
435 // wrap
436 return true;
437 }
438 return false;
439}
440
441WebRtc_UWord32
442RTCPSender::LastSendReport( WebRtc_UWord32& lastRTCPTime)
443{
444 CriticalSectionScoped lock(_criticalSectionRTCPSender);
445
446 lastRTCPTime = _lastRTCPTime[0];
447 return _lastSendReport[0];
448}
449
450WebRtc_UWord32
451RTCPSender::SendTimeOfSendReport(const WebRtc_UWord32 sendReport)
452{
453 CriticalSectionScoped lock(_criticalSectionRTCPSender);
454
455 // This is only saved when we are the sender
456 if((_lastSendReport[0] == 0) || (sendReport == 0))
457 {
458 return 0; // will be ignored
459 } else
460 {
461 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
462 {
463 if( _lastSendReport[i] == sendReport)
464 {
465 return _lastRTCPTime[i];
466 }
467 }
468 }
469 return 0;
470}
471
472WebRtc_Word32
473RTCPSender::AddReportBlock(const WebRtc_UWord32 SSRC,
474 const RTCPReportBlock* reportBlock)
475{
476 if(reportBlock == NULL)
477 {
478 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
479 return -1;
480 }
481
482 CriticalSectionScoped lock(_criticalSectionRTCPSender);
483
484 if(_reportBlocks.Size() >= RTCP_MAX_REPORT_BLOCKS)
485 {
486 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
487 return -1;
488 }
489 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
490 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
491 _reportBlocks.Insert(SSRC, copyReportBlock);
492 return 0;
493}
494
495WebRtc_Word32
496RTCPSender::RemoveReportBlock(const WebRtc_UWord32 SSRC)
497{
498 CriticalSectionScoped lock(_criticalSectionRTCPSender);
499
500 MapItem* item= _reportBlocks.Find(SSRC);
501 if(item)
502 {
503 RTCPReportBlock* ptr= (RTCPReportBlock*)(item->GetItem());
504 if(ptr)
505 {
506 delete ptr;
507 }
508 _reportBlocks.Erase(item);
509 return 0;
510 }
511 return -1;
512}
513
514WebRtc_Word32
515RTCPSender::BuildSR(WebRtc_UWord8* rtcpbuffer,
516 WebRtc_UWord32& pos,
517 const WebRtc_UWord32 NTPsec,
518 const WebRtc_UWord32 NTPfrac,
519 const RTCPReportBlock* received)
520{
521 // sanity
522 if(pos + 52 >= IP_PACKET_SIZE)
523 {
524 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
525 return -2;
526 }
527 WebRtc_UWord32 RTPtime;
528 WebRtc_UWord32 BackTimedNTPsec;
529 WebRtc_UWord32 BackTimedNTPfrac;
530
531 WebRtc_UWord32 posNumberOfReportBlocks = pos;
532 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
533
534 // Sender report
535 rtcpbuffer[pos++]=(WebRtc_UWord8)200;
536
537 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
538 {
539 // shift old
540 _lastSendReport[i+1] = _lastSendReport[i];
541 _lastRTCPTime[i+1] =_lastRTCPTime[i];
542 }
543
544 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac); // before video cam compensation
545
546 if(_cameraDelayMS >= 0)
547 {
548 // fraction of a second as an unsigned word32 4.294 967 296E9
549 WebRtc_UWord32 cameraDelayFixFrac = (WebRtc_UWord32)_cameraDelayMS* 4294967; // note camera delay can't be larger than +/-1000ms
550 if(NTPfrac > cameraDelayFixFrac)
551 {
552 // no problem just reduce the fraction part
553 BackTimedNTPfrac = NTPfrac - cameraDelayFixFrac;
554 BackTimedNTPsec = NTPsec;
555 } else
556 {
557 // we need to reduce the sec and add that sec to the frac
558 BackTimedNTPsec = NTPsec - 1;
559 BackTimedNTPfrac = 0xffffffff - (cameraDelayFixFrac - NTPfrac);
560 }
561 } else
562 {
563 // fraction of a second as an unsigned word32 4.294 967 296E9
564 WebRtc_UWord32 cameraDelayFixFrac = (WebRtc_UWord32)(-_cameraDelayMS)* 4294967; // note camera delay can't be larger than +/-1000ms
565 if(NTPfrac > 0xffffffff - cameraDelayFixFrac)
566 {
567 // we need to add the sec and add that sec to the frac
568 BackTimedNTPsec = NTPsec + 1;
569 BackTimedNTPfrac = cameraDelayFixFrac + NTPfrac; // this will wrap but that is ok
570 } else
571 {
572 // no problem just add the fraction part
573 BackTimedNTPsec = NTPsec;
574 BackTimedNTPfrac = NTPfrac + cameraDelayFixFrac;
575 }
576 }
577 _lastSendReport[0] = (BackTimedNTPsec <<16) + (BackTimedNTPfrac >> 16);
578
579 // RTP timestamp
580 // This should have a ramdom start value added
581 // RTP is counted from NTP not the acctual RTP
582 // This reflects the perfect RTP time
583 // we solve this by initiating RTP to our NTP :)
584
585 WebRtc_UWord32 freqHz = 90000; // For video
586 if(_audio)
587 {
588 freqHz = _cbRtcpPrivate.CurrentSendFrequencyHz();
589 RTPtime = ModuleRTPUtility::CurrentRTP(freqHz);
590 }
591 else // video
592 {
593 // used to be (WebRtc_UWord32)(((float)BackTimedNTPfrac/(float)FRAC)* 90000)
594 WebRtc_UWord32 tmp = 9*(BackTimedNTPfrac/429496);
595 RTPtime = BackTimedNTPsec*freqHz + tmp;
596 }
597
598
599
600
601 // Add sender data
602 // Save for our length field
603 pos++;
604 pos++;
605
606 // Add our own SSRC
607 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
608 pos += 4;
609 // NTP
610 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, BackTimedNTPsec);
611 pos += 4;
612 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, BackTimedNTPfrac);
613 pos += 4;
614 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
615 pos += 4;
616
617 //sender's packet count
618 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _cbRtcpPrivate.PacketCountSent());
619 pos += 4;
620
621 //sender's octet count
622 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _cbRtcpPrivate.ByteCountSent());
623 pos += 4;
624
625 WebRtc_UWord8 numberOfReportBlocks = 0;
626 WebRtc_Word32 retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
627 if(retVal < 0)
628 {
629 //
630 return retVal ;
631 }
632 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
633
634 WebRtc_UWord16 len = WebRtc_UWord16((pos/4) -1);
635 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
636 return 0;
637}
638
639
640WebRtc_Word32
641RTCPSender::BuildSDEC(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
642{
643 WebRtc_UWord32 lengthCname =(WebRtc_UWord32)strlen((char*)_CNAME);
644
645 // sanity max is 255
646 if(lengthCname > RTCP_CNAME_SIZE)
647 {
648 lengthCname = RTCP_CNAME_SIZE;
649 }
650 // sanity
651 if(pos + 12+ lengthCname >= IP_PACKET_SIZE)
652 {
653 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
654 return -2;
655 }
656 // SDEC Source Description
657
658 // We always need to add SDES CNAME
659 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1 + _csrcCNAMEs.Size(); // source counts
660 rtcpbuffer[pos++]=(WebRtc_UWord8)202;
661
662 // handle SDES length later on
663 WebRtc_UWord32 SDESLengthPos = pos;
664 pos++;
665 pos++;
666
667 // Add our own SSRC
668 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
669 pos += 4;
670
671 // CNAME = 1
672 rtcpbuffer[pos++]=(WebRtc_UWord8)1;
673
674 //
675 rtcpbuffer[pos++]=(WebRtc_UWord8)lengthCname;
676
677 WebRtc_UWord16 SDESLength = 10;
678
679 memcpy(&rtcpbuffer[pos],_CNAME,lengthCname);
680 pos += lengthCname;
681 SDESLength += (WebRtc_UWord16)lengthCname;
682
683 WebRtc_UWord16 padding =0;
684
685 // We must have a zero field even if we have an even multiple of 4 bytes
686 if((pos % 4) ==0)
687 {
688 padding++;
689 rtcpbuffer[pos++]=0;
690 }
691 while((pos % 4) !=0)
692 {
693 padding++;
694 rtcpbuffer[pos++]=0;
695 }
696 SDESLength += padding;
697
698 MapItem* item = _csrcCNAMEs.First();
699
700 for(int i = 0; item && i < _csrcCNAMEs.Size(); i++)
701 {
702 RTCPUtility::RTCPCnameInformation* cname = (RTCPUtility::RTCPCnameInformation*)(item->GetItem());
703 WebRtc_UWord32 SSRC = item->GetUnsignedId();
704
705 // Add SSRC
706 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
707 pos += 4;
708
709 // CNAME = 1
710 rtcpbuffer[pos++]=(WebRtc_UWord8)1;
711
712 rtcpbuffer[pos++]= cname->length;
713
714 SDESLength += 6;
715
716 memcpy(&rtcpbuffer[pos],cname->name, cname->length);
717 pos += cname->length;
718 SDESLength += cname->length;
719
720 WebRtc_UWord16 padding =0;
721
722 // We must have a zero field even if we have an even multiple of 4 bytes
723 if((pos % 4) ==0)
724 {
725 padding++;
726 rtcpbuffer[pos++]=0;
727 }
728 while((pos % 4) !=0)
729 {
730 padding++;
731 rtcpbuffer[pos++]=0;
732 }
733 SDESLength += padding;
734
735 item = _csrcCNAMEs.Next(item);
736 }
737 WebRtc_UWord16 length = SDESLength;
738 length= (length/4) - 1; // in 32-bit words minus one and we dont count the header
739
740 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+SDESLengthPos, length);
741 return 0;
742}
743
744WebRtc_Word32
745RTCPSender::BuildRR(WebRtc_UWord8* rtcpbuffer,
746 WebRtc_UWord32& pos,
747 const WebRtc_UWord32 NTPsec,
748 const WebRtc_UWord32 NTPfrac,
749 const RTCPReportBlock* received)
750{
751 // sanity one block
752 if(pos + 32 >= IP_PACKET_SIZE)
753 {
754 return -2;
755 }
756 WebRtc_UWord32 posNumberOfReportBlocks = pos;
757
758 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
759 rtcpbuffer[pos++]=(WebRtc_UWord8)201;
760
761 // Save for our length field
762 pos++;
763 pos++;
764
765 // Add our own SSRC
766 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
767 pos += 4;
768
769 WebRtc_UWord8 numberOfReportBlocks = 0;
770 WebRtc_Word32 retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
771 if(retVal < 0)
772 {
773 return retVal;
774 }
775 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
776
777 WebRtc_UWord16 len = WebRtc_UWord16((pos)/4 -1);
778 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
779 return 0;
780}
781
782WebRtc_Word32
783RTCPSender::BuildPLI(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
784{
785 // sanity
786 if(pos + 12 >= IP_PACKET_SIZE)
787 {
788 return -2;
789 }
790 // add picture loss indicator
791 WebRtc_UWord8 FMT = 1;
792 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
793 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
794
795 //Used fixed length of 2
796 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
797 rtcpbuffer[pos++]=(WebRtc_UWord8)(2);
798
799 // Add our own SSRC
800 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
801 pos += 4;
802
803 // Add the remote SSRC
804 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
805 pos += 4;
806 return 0;
807}
808
809WebRtc_Word32
810RTCPSender::BuildFIR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos, const WebRtc_UWord32 RTT)
811{
812 bool firRepeat = false;
813 WebRtc_UWord32 diff = ModuleRTPUtility::GetTimeInMS() - _lastTimeFIR;
814 if(diff < RTT + 3) // 3 is processing jitter
815 {
816 // we have recently sent a FIR
817 // don't send another
818 return 0;
819
820 } else
821 {
822 if(diff < (RTT*2 + RTCP_MIN_FRAME_LENGTH_MS))
823 {
824 // send a FIR_REPEAT instead of a FIR
825 firRepeat = true;
826 }
827 }
828 _lastTimeFIR = ModuleRTPUtility::GetTimeInMS();
829 if(!firRepeat)
830 {
831 _sequenceNumberFIR++; // do not increase if repetition
832 }
833
834 // sanity
835 if(pos + 20 >= IP_PACKET_SIZE)
836 {
837 return -2;
838 }
839
840 // add full intra request indicator
841 WebRtc_UWord8 FMT = 4;
842 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
843 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
844
845 //Length of 4
846 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
847 rtcpbuffer[pos++]=(WebRtc_UWord8)(4);
848
849 // Add our own SSRC
850 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
851 pos += 4;
852
853 // RFC 5104 4.3.1.2. Semantics
854
855 // SSRC of media source
856 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
857 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
858 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
859 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
860
861 // Additional Feedback Control Information (FCI)
862 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
863 pos += 4;
864
865 rtcpbuffer[pos++]=(WebRtc_UWord8)(_sequenceNumberFIR);
866 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
867 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
868 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
869 return 0;
870}
871
872/*
873 0 1 2 3
874 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
875 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
876 | First | Number | PictureID |
877 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
878*/
879WebRtc_Word32
880RTCPSender::BuildSLI(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos, const WebRtc_UWord8 pictureID)
881{
882 // sanity
883 if(pos + 16 >= IP_PACKET_SIZE)
884 {
885 return -2;
886 }
887 // add slice loss indicator
888 WebRtc_UWord8 FMT = 2;
889 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
890 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
891
892 //Used fixed length of 3
893 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
894 rtcpbuffer[pos++]=(WebRtc_UWord8)(3);
895
896 // Add our own SSRC
897 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
898 pos += 4;
899
900 // Add the remote SSRC
901 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
902 pos += 4;
903
904 // Add first, number & picture ID 6 bits
905 // first = 0, 13 - bits
906 // number = 0x1fff, 13 - bits only ones for now
907 WebRtc_UWord32 sliField = (0x1fff << 6)+ (0x3f & pictureID);
908 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
909 pos += 4;
910 return 0;
911}
912
913/*
914 0 1 2 3
915 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
916 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
917 | PB |0| Payload Type| Native RPSI bit string |
918 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
919 | defined per codec ... | Padding (0) |
920 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
921*/
922/*
923* Note: not generic made for VP8
924*/
925WebRtc_Word32
926RTCPSender::BuildRPSI(WebRtc_UWord8* rtcpbuffer,
927 WebRtc_UWord32& pos,
928 const WebRtc_UWord64 pictureID,
929 const WebRtc_UWord8 payloadType)
930{
931 // sanity
932 if(pos + 24 >= IP_PACKET_SIZE)
933 {
934 return -2;
935 }
936 // add Reference Picture Selection Indication
937 WebRtc_UWord8 FMT = 3;
938 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
939 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
940
941 // calc length
942 WebRtc_UWord32 bitsRequired = 7;
943 WebRtc_UWord8 bytesRequired = 1;
944 while((pictureID>>bitsRequired) > 0)
945 {
946 bitsRequired += 7;
947 bytesRequired++;
948 }
949
950 WebRtc_UWord8 size = 3;
951 if(bytesRequired > 6)
952 {
953 size = 5;
954 } else if(bytesRequired > 2)
955 {
956 size = 4;
957 }
958 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
959 rtcpbuffer[pos++]=size;
960
961 // Add our own SSRC
962 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
963 pos += 4;
964
965 // Add the remote SSRC
966 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
967 pos += 4;
968
969 // calc padding length
970 WebRtc_UWord8 paddingBytes = 4-((2+bytesRequired)%4);
971 if(paddingBytes == 4)
972 {
973 paddingBytes = 0;
974 }
975 // add padding length in bits
976 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
977 pos++;
978
979 // add payload type
980 rtcpbuffer[pos] = payloadType;
981 pos++;
982
983 // add picture ID
984 for(int i = bytesRequired-1; i > 0; i--)
985 {
986 rtcpbuffer[pos] = 0x80 | WebRtc_UWord8(pictureID >> (i*7));
987 pos++;
988 }
989 // add last byte of picture ID
990 rtcpbuffer[pos] = WebRtc_UWord8(pictureID & 0x7f);
991 pos++;
992
993 // add padding
994 for(int j = 0; j <paddingBytes; j++)
995 {
996 rtcpbuffer[pos] = 0;
997 pos++;
998 }
999 return 0;
1000}
1001
1002WebRtc_Word32
1003RTCPSender::BuildTMMBR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos, WebRtc_UWord32 RTT)
1004{
1005 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1006 // If the sender is an owner of the TMMBN -> send TMMBR
1007 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1008
1009 // About to send TMMBR, first run remote rate control
1010 // to get a target bit rate.
1011 _tmmbr_Send = _remoteRateControl.TargetBitRate(RTT) / 1000;
1012
1013 // get current bounding set from RTCP receiver
1014 bool tmmbrOwner = false;
1015 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet(); // store in candidateSet, allocates one extra slot
1016
1017 // holding _criticalSectionRTCPSender while calling RTCPreceiver which will accuire _criticalSectionRTCPReceiver
1018 // is a potental deadlock but since RTCPreceiver is not doing the revese we should be fine
1019 WebRtc_Word32 lengthOfBoundingSet = _cbRtcpPrivate.BoundingSet(tmmbrOwner, candidateSet);
1020
1021 if(lengthOfBoundingSet > 0)
1022 {
1023 for (WebRtc_Word32 i = 0; i < lengthOfBoundingSet; i++)
1024 {
1025 if( candidateSet->ptrTmmbrSet[i] == _tmmbr_Send &&
1026 candidateSet->ptrPacketOHSet[i] == _packetOH_Send)
1027 {
1028 // do not send the same tuple
1029 return 0;
1030 }
1031 }
1032 if(!tmmbrOwner)
1033 {
1034 // use received bounding set as candidate set
1035 // add current tuple
1036 candidateSet->ptrTmmbrSet[lengthOfBoundingSet] = _tmmbr_Send;
1037 candidateSet->ptrPacketOHSet[lengthOfBoundingSet] = _packetOH_Send;
1038 candidateSet->ptrSsrcSet[lengthOfBoundingSet] = _SSRC;
1039 int numCandidates = lengthOfBoundingSet+ 1;
1040
1041 // find bounding set
1042 TMMBRSet* boundingSet = NULL;
1043 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1044 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1045 {
1046 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1047 }
1048 if(!tmmbrOwner)
1049 {
1050 // did not enter bounding set, no meaning to send this request
1051 return 0;
1052 }
1053 }
1054 }
1055
1056 if(_tmmbr_Send)
1057 {
1058 // sanity
1059 if(pos + 20 >= IP_PACKET_SIZE)
1060 {
1061 return -2;
1062 }
1063 // add TMMBR indicator
1064 WebRtc_UWord8 FMT = 3;
1065 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1066 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1067
1068 //Length of 4
1069 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1070 rtcpbuffer[pos++]=(WebRtc_UWord8)(4);
1071
1072 // Add our own SSRC
1073 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1074 pos += 4;
1075
1076 // RFC 5104 4.2.1.2. Semantics
1077
1078 // SSRC of media source
1079 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1080 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1081 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1082 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1083
1084 // Additional Feedback Control Information (FCI)
1085 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1086 pos += 4;
1087
1088 WebRtc_UWord32 bitRate = _tmmbr_Send*1000;
1089 WebRtc_UWord32 mmbrExp = 0;
1090 for(WebRtc_UWord32 i=0;i<64;i++)
1091 {
1092 if(bitRate <= ((WebRtc_UWord32)131071 << i))
1093 {
1094 mmbrExp = i;
1095 break;
1096 }
1097 }
1098 WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp);
1099
1100 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1101 rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);
1102 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1103 rtcpbuffer[pos++]=(WebRtc_UWord8)(_packetOH_Send);
1104 }
1105 return 0;
1106}
1107
1108WebRtc_Word32
1109RTCPSender::BuildTMMBN(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1110{
1111 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1112 if(boundingSet == NULL)
1113 {
1114 return -1;
1115 }
1116 // sanity
1117 if(pos + 12 + boundingSet->lengthOfSet*8 >= IP_PACKET_SIZE)
1118 {
1119 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1120 return -2;
1121 }
1122 WebRtc_UWord8 FMT = 4;
1123 // add TMMBN indicator
1124 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1125 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1126
1127 //Add length later
1128 int posLength = pos;
1129 pos++;
1130 pos++;
1131
1132 // Add our own SSRC
1133 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1134 pos += 4;
1135
1136 // RFC 5104 4.2.2.2. Semantics
1137
1138 // SSRC of media source
1139 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1140 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1141 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1142 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1143
1144 // Additional Feedback Control Information (FCI)
1145 int numBoundingSet = 0;
1146 for(WebRtc_UWord32 n=0; n< boundingSet->lengthOfSet; n++)
1147 {
1148 if (boundingSet->ptrTmmbrSet[n] > 0)
1149 {
1150 WebRtc_UWord32 tmmbrSSRC = boundingSet->ptrSsrcSet[n];
1151 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1152 pos += 4;
1153
1154 WebRtc_UWord32 bitRate = boundingSet->ptrTmmbrSet[n] * 1000;
1155 WebRtc_UWord32 mmbrExp = 0;
1156 for(int i=0; i<64; i++)
1157 {
1158 if(bitRate <= ((WebRtc_UWord32)131071 << i))
1159 {
1160 mmbrExp = i;
1161 break;
1162 }
1163 }
1164 WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp);
1165 WebRtc_UWord32 measuredOH = boundingSet->ptrPacketOHSet[n];
1166
1167 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1168 rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);
1169 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1170 rtcpbuffer[pos++]=(WebRtc_UWord8)(measuredOH);
1171 numBoundingSet++;
1172 }
1173 }
1174 WebRtc_UWord16 length= (WebRtc_UWord16)(2+2*numBoundingSet);
1175 rtcpbuffer[posLength++]=(WebRtc_UWord8)(length>>8);
1176 rtcpbuffer[posLength]=(WebRtc_UWord8)(length);
1177 return 0;
1178}
1179
1180WebRtc_Word32
1181RTCPSender::BuildAPP(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1182{
1183 // sanity
1184 if(_appData == NULL)
1185 {
1186 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1187 return -1;
1188 }
1189 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1190 {
1191 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1192 return -2;
1193 }
1194 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + _appSubType;
1195
1196 // Add APP ID
1197 rtcpbuffer[pos++]=(WebRtc_UWord8)204;
1198
1199 WebRtc_UWord16 length = (_appLength>>2) + 2; // include SSRC and name
1200 rtcpbuffer[pos++]=(WebRtc_UWord8)(length>>8);
1201 rtcpbuffer[pos++]=(WebRtc_UWord8)(length);
1202
1203 // Add our own SSRC
1204 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1205 pos += 4;
1206
1207 // Add our application name
1208 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1209 pos += 4;
1210
1211 // Add the data
1212 memcpy(rtcpbuffer +pos, _appData,_appLength);
1213 pos += _appLength;
1214 return 0;
1215}
1216
1217WebRtc_Word32
1218RTCPSender::BuildNACK(WebRtc_UWord8* rtcpbuffer,
1219 WebRtc_UWord32& pos,
1220 const WebRtc_Word32 nackSize,
1221 const WebRtc_UWord16* nackList)
1222{
1223 // sanity
1224 if(pos + 16 >= IP_PACKET_SIZE)
1225 {
1226 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1227 return -2;
1228 }
1229
1230 // int size, WebRtc_UWord16* nackList
1231 // add nack list
1232 WebRtc_UWord8 FMT = 1;
1233 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1234 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1235
1236 rtcpbuffer[pos++]=(WebRtc_UWord8) 0;
1237 int nackSizePos = pos;
1238 rtcpbuffer[pos++]=(WebRtc_UWord8)(3); //setting it to one kNACK signal as default
1239
1240 // Add our own SSRC
1241 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1242 pos += 4;
1243
1244 // Add the remote SSRC
1245 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1246 pos += 4;
1247
1248 // add the list
1249 int i = 0;
1250 int numOfNackFields = 0;
1251 while(nackSize > i && numOfNackFields < 253)
1252 {
1253 WebRtc_UWord16 nack = nackList[i];
1254 // put dow our sequence number
1255 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, nack);
1256 pos += 2;
1257
1258 i++;
1259 numOfNackFields++;
1260 if(nackSize > i)
1261 {
1262 bool moreThan16Away = (WebRtc_UWord16(nack+16) < nackList[i])?true: false;
1263 if(!moreThan16Away)
1264 {
1265 // check for a wrap
1266 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1267 {
1268 // wrap
1269 moreThan16Away = true;
1270 }
1271 }
1272 if(moreThan16Away)
1273 {
1274 // next is more than 16 away
1275 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1276 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1277 } else
1278 {
1279 // build our bitmask
1280 WebRtc_UWord16 bitmask = 0;
1281
1282 bool within16Away = (WebRtc_UWord16(nack+16) > nackList[i])?true: false;
1283 if(within16Away)
1284 {
1285 // check for a wrap
1286 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1287 {
1288 // wrap
1289 within16Away = false;
1290 }
1291 }
1292
1293 while( nackSize > i && within16Away)
1294 {
1295 WebRtc_Word16 shift = (nackList[i]-nack)-1;
1296 assert(!(shift > 15) && !(shift < 0));
1297
1298 bitmask += (1<< shift);
1299 i++;
1300 if(nackSize > i)
1301 {
1302 within16Away = (WebRtc_UWord16(nack+16) > nackList[i])?true: false;
1303 if(within16Away)
1304 {
1305 // check for a wrap
1306 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1307 {
1308 // wrap
1309 within16Away = false;
1310 }
1311 }
1312 }
1313 }
1314 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, bitmask);
1315 pos += 2;
1316 }
1317 // sanity do we have room from one more 4 byte block?
1318 if(pos + 4 >= IP_PACKET_SIZE)
1319 {
1320 return -2;
1321 }
1322 } else
1323 {
1324 // no more in the list
1325 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1326 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1327 }
1328 }
1329 rtcpbuffer[nackSizePos]=(WebRtc_UWord8)(2+numOfNackFields);
1330 return 0;
1331}
1332
1333WebRtc_Word32
1334RTCPSender::BuildBYE(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1335{
1336 // sanity
1337 if(pos + 8 >= IP_PACKET_SIZE)
1338 {
1339 return -2;
1340 }
1341 if(_includeCSRCs)
1342 {
1343 // Add a bye packet
1344 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1345 rtcpbuffer[pos++]=(WebRtc_UWord8)203;
1346
1347 // length
1348 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1349 rtcpbuffer[pos++]=(WebRtc_UWord8)(1 + _CSRCs);
1350
1351 // Add our own SSRC
1352 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1353 pos += 4;
1354
1355 // add CSRCs
1356 for(int i = 0; i < _CSRCs; i++)
1357 {
1358 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1359 pos += 4;
1360 }
1361 } else
1362 {
1363 // Add a bye packet
1364 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1; // number of SSRC+CSRCs
1365 rtcpbuffer[pos++]=(WebRtc_UWord8)203;
1366
1367 // length
1368 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1369 rtcpbuffer[pos++]=(WebRtc_UWord8)1;
1370
1371 // Add our own SSRC
1372 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1373 pos += 4;
1374 }
1375 return 0;
1376}
1377
1378WebRtc_Word32
1379RTCPSender::BuildVoIPMetric(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1380{
1381 // sanity
1382 if(pos + 44 >= IP_PACKET_SIZE)
1383 {
1384 return -2;
1385 }
1386
1387 // Add XR header
1388 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
1389 rtcpbuffer[pos++]=(WebRtc_UWord8)207;
1390
1391 WebRtc_UWord32 XRLengthPos = pos;
1392
1393 // handle length later on
1394 pos++;
1395 pos++;
1396
1397 // Add our own SSRC
1398 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1399 pos += 4;
1400
1401 // Add a VoIP metrics block
1402 rtcpbuffer[pos++]=7;
1403 rtcpbuffer[pos++]=0;
1404 rtcpbuffer[pos++]=0;
1405 rtcpbuffer[pos++]=8;
1406
1407 // Add the remote SSRC
1408 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1409 pos += 4;
1410
1411 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1412 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1413 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1414 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1415
1416 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.burstDuration >> 8);
1417 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.burstDuration);
1418 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.gapDuration >> 8);
1419 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.gapDuration);
1420
1421 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.roundTripDelay >> 8);
1422 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.roundTripDelay);
1423 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.endSystemDelay >> 8);
1424 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.endSystemDelay);
1425
1426 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1427 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1428 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1429 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1430
1431 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1432 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1433 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1434 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1435
1436 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1437 rtcpbuffer[pos++] = 0; // reserved
1438 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBnominal >> 8);
1439 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBnominal);
1440
1441 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBmax >> 8);
1442 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBmax);
1443 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBabsMax >> 8);
1444 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBabsMax);
1445
1446 rtcpbuffer[XRLengthPos]=(WebRtc_UWord8)(0);
1447 rtcpbuffer[XRLengthPos+1]=(WebRtc_UWord8)(10);
1448 return 0;
1449}
1450
1451WebRtc_Word32
1452RTCPSender::SendRTCP(const WebRtc_UWord32 packetTypeFlags,
1453 const WebRtc_Word32 nackSize, // NACK
1454 const WebRtc_UWord16* nackList, // NACK
1455 const WebRtc_UWord32 RTT, // FIR
1456 const WebRtc_UWord64 pictureID) // SLI & RPSI
1457{
1458 WebRtc_UWord32 rtcpPacketTypeFlags = packetTypeFlags;
1459 WebRtc_UWord32 pos = 0;
1460 WebRtc_UWord8 rtcpbuffer[IP_PACKET_SIZE];
1461
1462 if(_method == kRtcpOff)
1463 {
1464 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1465 return -1;
1466 }
1467
1468 do // only to be able to use break :) (and the critsect must be inside its own scope)
1469 {
1470 // collect the received information
1471 RTCPReportBlock received;
1472 bool hasReceived = false;
1473 WebRtc_UWord32 NTPsec = 0;
1474 WebRtc_UWord32 NTPfrac = 0;
1475
1476 if( _method == kRtcpCompound ||
1477 rtcpPacketTypeFlags & kRtcpReport ||
1478 rtcpPacketTypeFlags & kRtcpSr ||
1479 rtcpPacketTypeFlags & kRtcpRr)
1480 {
1481 // get statistics from our RTPreceiver outside critsect
1482 if(_cbRtcpPrivate.ReportBlockStatistics(&received.fractionLost,
1483 &received.cumulativeLost,
1484 &received.extendedHighSeqNum,
1485 &received.jitter) == 0)
1486 {
1487 hasReceived = true;
1488
1489 WebRtc_UWord32 lastReceivedRRNTPsecs = 0;
1490 WebRtc_UWord32 lastReceivedRRNTPfrac = 0;
1491 WebRtc_UWord32 remoteSR = 0;
1492
1493 // ok even if we have not received a SR, we will send 0 in that case
1494 _cbRtcpPrivate.LastReceivedNTP(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac, remoteSR);
1495
1496 // get our NTP as late as possible to avoid a race
1497 ModuleRTPUtility::CurrentNTP(NTPsec, NTPfrac);
1498
1499 // Delay since last received report
1500 WebRtc_UWord32 delaySinceLastReceivedSR = 0;
1501 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
1502 {
1503 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1504 WebRtc_UWord32 now=NTPsec&0x0000FFFF;
1505 now <<=16;
1506 now += (NTPfrac&0xffff0000)>>16;
1507
1508 WebRtc_UWord32 receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
1509 receiveTime <<=16;
1510 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1511
1512 delaySinceLastReceivedSR = now-receiveTime;
1513 }
1514 received.delaySinceLastSR = delaySinceLastReceivedSR;
1515 received.lastSR = remoteSR;
1516 } else
1517 {
1518 // we need to send our NTP even if we dont have received any reports
1519 ModuleRTPUtility::CurrentNTP(NTPsec, NTPfrac);
1520 }
1521 }
1522
1523 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1524
1525 if(_TMMBR ) // attach TMMBR to send and receive reports
1526 {
1527 rtcpPacketTypeFlags |= kRtcpTmmbr;
1528 }
1529 if(_appSend)
1530 {
1531 rtcpPacketTypeFlags |= kRtcpApp;
1532 _appSend = false;
1533 }
1534 if(_xrSendVoIPMetric)
1535 {
1536 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1537 _xrSendVoIPMetric = false;
1538 }
1539 if(_sendTMMBN) // set when having received a TMMBR
1540 {
1541 rtcpPacketTypeFlags |= kRtcpTmmbn;
1542 _sendTMMBN = false;
1543 }
1544
1545 if(_method == kRtcpCompound)
1546 {
1547 if(_sending)
1548 {
1549 rtcpPacketTypeFlags |= kRtcpSr;
1550 } else
1551 {
1552 rtcpPacketTypeFlags |= kRtcpRr;
1553 }
1554 } else if(_method == kRtcpNonCompound)
1555 {
1556 if(rtcpPacketTypeFlags & kRtcpReport)
1557 {
1558 if(_sending)
1559 {
1560 rtcpPacketTypeFlags |= kRtcpSr;
1561 } else
1562 {
1563 rtcpPacketTypeFlags |= kRtcpRr;
1564 }
1565 }
1566 }
1567 if( rtcpPacketTypeFlags & kRtcpRr ||
1568 rtcpPacketTypeFlags & kRtcpSr)
1569 {
1570 // generate next time to send a RTCP report
1571 // seeded from RTP constructor
1572 WebRtc_Word32 random = rand() % 1000;
1573 WebRtc_Word32 timeToNext = RTCP_INTERVAL_AUDIO_MS;
1574
1575 if(_audio)
1576 {
1577 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
1578 }else
1579 {
1580 WebRtc_UWord32 minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1581 if(_sending)
1582 {
1583 // calc bw for video 360/sendBW in kbit/s
1584 WebRtc_Word32 sendBitrateKbit = _cbRtcpPrivate.BitrateSent()/1000;
1585 if(sendBitrateKbit != 0)
1586 {
1587 minIntervalMs = 360000/sendBitrateKbit;
1588 }
1589 }
1590 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1591 {
1592 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1593 }
1594 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1595 }
1596 _nextTimeToSendRTCP = ModuleRTPUtility::GetTimeInMS() + timeToNext;
1597 }
1598
1599 // if the data does not fitt in the packet we fill it as much as possible
1600 WebRtc_Word32 buildVal = 0;
1601
1602 if(rtcpPacketTypeFlags & kRtcpSr)
1603 {
1604 if(hasReceived)
1605 {
1606 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
1607 } else
1608 {
1609 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac);
1610 }
1611 if(buildVal == -1)
1612 {
1613 return -1; // error
1614
1615 }else if(buildVal == -2)
1616 {
1617 break; // out of buffer
1618 }
1619 buildVal = BuildSDEC(rtcpbuffer, pos);
1620 if(buildVal == -1)
1621 {
1622 return -1; // error
1623
1624 }else if(buildVal == -2)
1625 {
1626 break; // out of buffer
1627 }
1628
1629 }else if(rtcpPacketTypeFlags & kRtcpRr)
1630 {
1631 if(hasReceived)
1632 {
1633 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
1634 }else
1635 {
1636 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
1637 }
1638 if(buildVal == -1)
1639 {
1640 return -1; // error
1641
1642 }else if(buildVal == -2)
1643 {
1644 break; // out of buffer
1645 }
1646 // only of set
1647 if(_CNAME[0] != 0)
1648 {
1649 buildVal = BuildSDEC(rtcpbuffer, pos);
1650 if(buildVal == -1)
1651 {
1652 return -1; // error
1653 }
1654 }
1655 }
1656 if(rtcpPacketTypeFlags & kRtcpPli)
1657 {
1658 buildVal = BuildPLI(rtcpbuffer, pos);
1659 if(buildVal == -1)
1660 {
1661 return -1; // error
1662
1663 }else if(buildVal == -2)
1664 {
1665 break; // out of buffer
1666 }
1667 }
1668 if(rtcpPacketTypeFlags & kRtcpFir)
1669 {
1670 buildVal = BuildFIR(rtcpbuffer, pos, RTT);
1671 if(buildVal == -1)
1672 {
1673 return -1; // error
1674
1675 }else if(buildVal == -2)
1676 {
1677 break; // out of buffer
1678 }
1679 }
1680 if(rtcpPacketTypeFlags & kRtcpSli)
1681 {
1682 buildVal = BuildSLI(rtcpbuffer, pos, (WebRtc_UWord8)pictureID);
1683 if(buildVal == -1)
1684 {
1685 return -1; // error
1686
1687 }else if(buildVal == -2)
1688 {
1689 break; // out of buffer
1690 }
1691 }
1692 if(rtcpPacketTypeFlags & kRtcpRpsi)
1693 {
1694 const WebRtc_Word8 payloadType = _cbRtcpPrivate.SendPayloadType();
1695 if(payloadType == -1)
1696 {
1697 return -1;
1698 }
1699 buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (WebRtc_UWord8)payloadType);
1700 if(buildVal == -1)
1701 {
1702 return -1; // error
1703
1704 }else if(buildVal == -2)
1705 {
1706 break; // out of buffer
1707 }
1708 }
1709 if(rtcpPacketTypeFlags & kRtcpBye)
1710 {
1711 buildVal = BuildBYE(rtcpbuffer, pos);
1712 if(buildVal == -1)
1713 {
1714 return -1; // error
1715
1716 }else if(buildVal == -2)
1717 {
1718 break; // out of buffer
1719 }
1720 }
1721 if(rtcpPacketTypeFlags & kRtcpApp)
1722 {
1723 buildVal = BuildAPP(rtcpbuffer, pos);
1724 if(buildVal == -1)
1725 {
1726 return -1; // error
1727
1728 }else if(buildVal == -2)
1729 {
1730 break; // out of buffer
1731 }
1732 }
1733 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1734 {
1735 buildVal = BuildTMMBR(rtcpbuffer, pos, RTT);
1736 if(buildVal == -1)
1737 {
1738 return -1; // error
1739
1740 }else if(buildVal == -2)
1741 {
1742 break; // out of buffer
1743 }
1744 }
1745 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1746 {
1747 buildVal = BuildTMMBN(rtcpbuffer, pos);
1748 if(buildVal == -1)
1749 {
1750 return -1; // error
1751
1752 }else if(buildVal == -2)
1753 {
1754 break; // out of buffer
1755 }
1756 }
1757 if(rtcpPacketTypeFlags & kRtcpNack)
1758 {
1759 buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList);
1760 if(buildVal == -1)
1761 {
1762 return -1; // error
1763
1764 }else if(buildVal == -2)
1765 {
1766 break; // out of buffer
1767 }
1768 }
1769 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1770 {
1771 buildVal = BuildVoIPMetric(rtcpbuffer, pos);
1772 if(buildVal == -1)
1773 {
1774 return -1; // error
1775
1776 }else if(buildVal == -2)
1777 {
1778 break; // out of buffer
1779 }
1780 }
1781 }while (false);
1782
1783 return SendToNetwork(rtcpbuffer, (WebRtc_UWord16)pos);
1784}
1785
1786WebRtc_Word32
1787RTCPSender::SendToNetwork(const WebRtc_UWord8* dataBuffer,
1788 const WebRtc_UWord16 length)
1789{
1790 CriticalSectionScoped lock(_criticalSectionTransport);
1791 if(_cbTransport)
1792 {
1793 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1794 {
1795 return 0;
1796 }
1797 }
1798 return -1;
1799}
1800
1801WebRtc_Word32
1802RTCPSender::SetCSRCStatus(const bool include)
1803{
1804 _includeCSRCs = include;
1805 return 0;
1806}
1807
1808WebRtc_Word32
1809RTCPSender::SetCSRCs(const WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize],
1810 const WebRtc_UWord8 arrLength)
1811{
1812 if(arrLength > kRtpCsrcSize)
1813 {
1814 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1815 assert(false);
1816 return -1;
1817 }
1818
1819 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1820
1821 for(int i = 0; i < arrLength;i++)
1822 {
1823 _CSRC[i] = arrOfCSRC[i];
1824 }
1825 _CSRCs = arrLength;
1826 return 0;
1827}
1828
1829WebRtc_Word32
1830RTCPSender::SetApplicationSpecificData(const WebRtc_UWord8 subType,
1831 const WebRtc_UWord32 name,
1832 const WebRtc_UWord8* data,
1833 const WebRtc_UWord16 length)
1834{
1835 if(length %4 != 0)
1836 {
1837 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1838 return -1;
1839 }
1840 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1841
1842 if(_appData)
1843 {
1844 delete [] _appData;
1845 }
1846
1847 _appSend = true;
1848 _appSubType = subType;
1849 _appName = name;
1850 _appData = new WebRtc_UWord8[length];
1851 _appLength = length;
1852 memcpy(_appData, data, length);
1853 return 0;
1854}
1855
1856WebRtc_Word32
1857RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
1858{
1859 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1860 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
1861
1862 _xrSendVoIPMetric = true;
1863 return 0;
1864}
1865
1866// called under critsect _criticalSectionRTCPSender
1867WebRtc_Word32
1868RTCPSender::AddReportBlocks(WebRtc_UWord8* rtcpbuffer,
1869 WebRtc_UWord32& pos,
1870 WebRtc_UWord8& numberOfReportBlocks,
1871 const RTCPReportBlock* received,
1872 const WebRtc_UWord32 NTPsec,
1873 const WebRtc_UWord32 NTPfrac)
1874{
1875 // sanity one block
1876 if(pos + 24 >= IP_PACKET_SIZE)
1877 {
1878 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1879 return -1;
1880 }
1881
1882 numberOfReportBlocks = _reportBlocks.Size();
1883 if(received)
1884 {
1885 // add our multiple RR to numberOfReportBlocks
1886 numberOfReportBlocks++;
1887 }
1888
1889 if(received)
1890 {
1891 // answer to the one that sends to me
1892 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac);
1893
1894 // Remote SSRC
1895 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1896 pos += 4;
1897
1898 // fraction lost
1899 rtcpbuffer[pos++]=received->fractionLost;
1900
1901 // cumulative loss
1902 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos, received->cumulativeLost);
1903 pos += 3;
1904
1905 // extended highest seq_no, contain the highest sequence number received
1906 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->extendedHighSeqNum);
1907 pos += 4;
1908
1909 //Jitter
1910 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
1911 pos += 4;
1912
1913 // Last SR timestamp, our NTP time when we received the last report
1914 // This is the value that we read from the send report packet not when we received it...
1915 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
1916 pos += 4;
1917
1918 // Delay since last received report,time since we received the report
1919 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->delaySinceLastSR);
1920 pos += 4;
1921 }
1922
1923 if(pos + _reportBlocks.Size()*24 >= IP_PACKET_SIZE)
1924 {
1925 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1926 return -1;
1927 }
1928
1929 MapItem* item = _reportBlocks.First();
1930 for(int i = 0; i < _reportBlocks.Size() && item; i++)
1931 {
1932 // we can have multiple report block in a conference
1933 WebRtc_UWord32 remoteSSRC = item->GetId();
1934 RTCPReportBlock* reportBlock = (RTCPReportBlock*)item->GetItem();
1935 if(reportBlock)
1936 {
1937 // Remote SSRC
1938 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
1939 pos += 4;
1940
1941 // fraction lost
1942 rtcpbuffer[pos++]=(WebRtc_UWord8)(reportBlock->fractionLost);
1943
1944 // cumulative loss
1945 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos, reportBlock->cumulativeLost);
1946 pos += 3;
1947
1948 // extended highest seq_no, contain the highest sequence number received
1949 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, reportBlock->extendedHighSeqNum);
1950 pos += 4;
1951
1952 //Jitter
1953 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, reportBlock->jitter);
1954 pos += 4;
1955
1956 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, reportBlock->lastSR);
1957 pos += 4;
1958
1959 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, reportBlock->delaySinceLastSR);
1960 pos += 4;
1961 }
1962 item = _reportBlocks.Next(item);
1963 }
1964 return pos;
1965}
1966
1967// no callbacks allowed inside this function
1968WebRtc_Word32
1969RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1970 const WebRtc_UWord32 maxBitrateKbit)
1971{
1972 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1973
1974 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
1975 {
1976 _sendTMMBN = true;
1977 return 0;
1978 }
1979 return -1;
1980}
1981
1982WebRtc_Word32
1983RTCPSender::RequestTMMBR(WebRtc_UWord32 estimatedBW, WebRtc_UWord32 packetOH)
1984{
1985 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1986 if(_TMMBR)
1987 {
1988 _tmmbr_Send = estimatedBW;
1989 _packetOH_Send = packetOH;
1990
1991 return 0;
1992 }
1993 return -1;
1994}
1995
1996RateControlRegion
1997RTCPSender::UpdateOverUseState(const RateControlInput& rateControlInput, bool& firstOverUse)
1998{
1999 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2000 return _remoteRateControl.Update(rateControlInput, firstOverUse);
2001}
2002} // namespace webrtc