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