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