1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
133f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <assert.h>  // assert
143f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <stdlib.h>  // rand
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <string.h>  // memcpy
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
173f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <algorithm>  // min
183f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org
19cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include "webrtc/common_types.h"
20cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
21cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
2299681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org#include "webrtc/system_wrappers/interface/logging.h"
23cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include "webrtc/system_wrappers/interface/trace_event.h"
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc {
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgusing RTCPUtility::RTCPCnameInformation;
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
29dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.comNACKStringBuilder::NACKStringBuilder() :
30dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    _stream(""), _count(0), _consecutive(false)
31dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com{
32dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    // Empty.
33dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com}
34dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com
359d71e286a6c8fa79d30fc6f55e0e6071de5d37e3pbos@webrtc.orgNACKStringBuilder::~NACKStringBuilder() {}
369d71e286a6c8fa79d30fc6f55e0e6071de5d37e3pbos@webrtc.org
37b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgvoid NACKStringBuilder::PushNACK(uint16_t nack)
38dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com{
39dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    if (_count == 0)
40dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    {
41dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com        _stream << nack;
42dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    } else if (nack == _prevNack + 1)
43dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    {
44dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com        _consecutive = true;
45dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    } else
46dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    {
47dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com        if (_consecutive)
48dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com        {
49dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com            _stream << "-" << _prevNack;
50dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com            _consecutive = false;
51dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com        }
52dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com        _stream << "," << nack;
53dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    }
54dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    _count++;
55dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    _prevNack = nack;
56dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com}
57dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com
58dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.comstd::string NACKStringBuilder::GetResult()
59dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com{
60dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    if (_consecutive)
61dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    {
62dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com        _stream << "-" << _prevNack;
63dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com        _consecutive = false;
64dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    }
65dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    return _stream.str();
66dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com}
67dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com
684e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.orgRTCPSender::FeedbackState::FeedbackState()
694e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org    : send_payload_type(0),
704e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org      frequency_hz(0),
71442dbd4c3639676395c03d8a47562f650f2c378fpbos@webrtc.org      packets_sent(0),
72442dbd4c3639676395c03d8a47562f650f2c378fpbos@webrtc.org      media_bytes_sent(0),
734e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org      send_bitrate(0),
744e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org      last_rr_ntp_secs(0),
754e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org      last_rr_ntp_frac(0),
76d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      remote_sr(0),
77d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      has_last_xr_rr(false) {}
784e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org
79b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgRTCPSender::RTCPSender(const int32_t id,
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                       const bool audio,
819858fc8df331a4111dc996469bcf027c4f986556stefan@webrtc.org                       Clock* clock,
82a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                       ReceiveStatistics* receive_statistics) :
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _id(id),
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _audio(audio),
851bb2146351979b6610107419b2a9c86cca2692a3stefan@webrtc.org    _clock(clock),
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _method(kRtcpOff),
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _cbTransport(NULL),
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _usingNack(false),
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _sending(false),
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _sendTMMBN(false),
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _REMB(false),
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _sendREMB(false),
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _TMMBR(false),
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _IJ(false),
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _nextTimeToSendRTCP(0),
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    start_timestamp_(0),
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    last_rtp_timestamp_(0),
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    last_frame_capture_time_ms_(-1),
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _SSRC(0),
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _remoteSSRC(0),
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _CNAME(),
105a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    receive_statistics_(receive_statistics),
106a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    internal_report_blocks_(),
107a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    external_report_blocks_(),
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _csrcCNAMEs(),
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11073ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org    _cameraDelayMS(0),
11173ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _lastSendReport(),
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _lastRTCPTime(),
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
115d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org    last_xr_rr_(),
116d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _CSRCs(0),
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _CSRC(),
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _includeCSRCs(true),
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _sequenceNumberFIR(0),
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _lengthRembSSRC(0),
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _sizeRembSSRC(0),
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _rembSSRC(NULL),
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _rembBitrate(0),
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _tmmbrHelp(),
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _tmmbr_Send(0),
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _packetOH_Send(0),
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _appSend(false),
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _appSubType(0),
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _appName(),
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _appData(NULL),
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _appLength(0),
137d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
138d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org    xrSendReceiverReferenceTimeEnabled_(false),
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _xrSendVoIPMetric(false),
1404a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org    _xrVoIPMetric()
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memset(_CNAME, 0, sizeof(_CNAME));
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memset(_lastSendReport, 0, sizeof(_lastSendReport));
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::~RTCPSender() {
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete [] _rembSSRC;
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete [] _appData;
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
151a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  while (!internal_report_blocks_.empty()) {
152a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    delete internal_report_blocks_.begin()->second;
153a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    internal_report_blocks_.erase(internal_report_blocks_.begin());
154a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
155a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  while (!external_report_blocks_.empty()) {
156b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    std::map<uint32_t, RTCPReportBlock*>::iterator it =
157a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        external_report_blocks_.begin();
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    delete it->second;
159a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    external_report_blocks_.erase(it);
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  while (!_csrcCNAMEs.empty()) {
162b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    std::map<uint32_t, RTCPCnameInformation*>::iterator it =
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        _csrcCNAMEs.begin();
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    delete it->second;
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _csrcCNAMEs.erase(it);
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete _criticalSectionTransport;
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete _criticalSectionRTCPSender;
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
171b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::RegisterSendTransport(Transport* outgoingTransport)
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionTransport);
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _cbTransport = outgoingTransport;
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPMethod
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::Status() const
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return _method;
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
186b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::SetRTCPStatus(const RTCPMethod method)
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(method != kRtcpOff)
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if(_audio)
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
1941bb2146351979b6610107419b2a9c86cca2692a3stefan@webrtc.org            _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
1959858fc8df331a4111dc996469bcf027c4f986556stefan@webrtc.org                (RTCP_INTERVAL_AUDIO_MS/2);
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        } else
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
1981bb2146351979b6610107419b2a9c86cca2692a3stefan@webrtc.org            _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
1999858fc8df331a4111dc996469bcf027c4f986556stefan@webrtc.org                (RTCP_INTERVAL_VIDEO_MS/2);
200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _method = method;
203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::Sending() const
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return _sending;
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
213b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
2144e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.orgRTCPSender::SetSendingStatus(const FeedbackState& feedback_state, bool sending)
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    bool sendRTCPBye = false;
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        CriticalSectionScoped lock(_criticalSectionRTCPSender);
219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if(_method != kRtcpOff)
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            if(sending == false && _sending == true)
223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // Trigger RTCP bye
225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                sendRTCPBye = true;
226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        _sending = sending;
229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(sendRTCPBye)
231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2324e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org        return SendRTCP(feedback_state, kRtcpBye);
233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool
238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::REMB() const
239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return _REMB;
242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
244b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::SetREMBStatus(const bool enable)
246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _REMB = enable;
249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
252b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
253b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgRTCPSender::SetREMBData(const uint32_t bitrate,
254b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                        const uint8_t numberOfSSRC,
255b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                        const uint32_t* SSRC)
256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _rembBitrate = bitrate;
25909da1a78127b1e5719daaf452f03d2012edad0dcstefan@webrtc.org
260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(_sizeRembSSRC < numberOfSSRC)
261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        delete [] _rembSSRC;
263b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        _rembSSRC = new uint32_t[numberOfSSRC];
264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        _sizeRembSSRC = numberOfSSRC;
26509da1a78127b1e5719daaf452f03d2012edad0dcstefan@webrtc.org    }
266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _lengthRembSSRC = numberOfSSRC;
268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (int i = 0; i < numberOfSSRC; i++)
26909da1a78127b1e5719daaf452f03d2012edad0dcstefan@webrtc.org    {
270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        _rembSSRC[i] = SSRC[i];
271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _sendREMB = true;
2735374dabd9f79f8f04c8b237a944771a46db25f27stefan@webrtc.org    // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
2745374dabd9f79f8f04c8b237a944771a46db25f27stefan@webrtc.org    // throttled by the caller.
2755374dabd9f79f8f04c8b237a944771a46db25f27stefan@webrtc.org    _nextTimeToSendRTCP = _clock->TimeInMilliseconds();
276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool
280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::TMMBR() const
281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return _TMMBR;
284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
286b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::SetTMMBRStatus(const bool enable)
288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _TMMBR = enable;
291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool
295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::IJ() const
296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return _IJ;
299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
301b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::SetIJStatus(const bool enable)
303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _IJ = enable;
306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
3100cb22cf7e4f9531a0f218e27c8ea0d0620cf05d7pbos@webrtc.org  CriticalSectionScoped lock(_criticalSectionRTCPSender);
311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  start_timestamp_ = start_timestamp;
312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                int64_t capture_time_ms) {
3161d25eacc9444fecc13c8b2ada929b531841df730henrika@webrtc.org  CriticalSectionScoped lock(_criticalSectionRTCPSender);
317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  last_rtp_timestamp_ = rtp_timestamp;
318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (capture_time_ms < 0) {
319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // We don't currently get a capture time from VoiceEngine.
32073ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org    last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    last_frame_capture_time_ms_ = capture_time_ms;
323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid
327b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgRTCPSender::SetSSRC( const uint32_t ssrc)
328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(_SSRC != 0)
332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // not first SetSSRC, probably due to a collision
334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // schedule a new RTCP report
335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // make sure that we send a RTP packet
3361bb2146351979b6610107419b2a9c86cca2692a3stefan@webrtc.org        _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _SSRC = ssrc;
339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
3417fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.orgvoid RTCPSender::SetRemoteSSRC(uint32_t ssrc)
342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _remoteSSRC = ssrc;
345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
34773ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.orgint32_t
34873ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.orgRTCPSender::SetCameraDelay(const int32_t delayMS)
34973ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org{
35073ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
35173ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org    if(delayMS > 1000 || delayMS < -1000)
35273ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org    {
35399681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org        LOG(LS_WARNING) << "Delay can't be larger than 1 second: "
35499681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org                        << delayMS << " ms";
35573ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org        return -1;
35673ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org    }
35773ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org    _cameraDelayMS = delayMS;
35873ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org    return 0;
35973ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org}
36073ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org
361b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (!cName)
363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped lock(_criticalSectionRTCPSender);
366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  _CNAME[RTCP_CNAME_SIZE - 1] = 0;
367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
371b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
372b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                                  const char cName[RTCP_CNAME_SIZE]) {
373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(cName);
374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped lock(_criticalSectionRTCPSender);
375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  RTCPCnameInformation* ptr = new RTCPCnameInformation();
379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ptr->name[RTCP_CNAME_SIZE - 1] = 0;
380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  _csrcCNAMEs[SSRC] = ptr;
382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
385b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped lock(_criticalSectionRTCPSender);
387b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  std::map<uint32_t, RTCPCnameInformation*>::iterator it =
388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      _csrcCNAMEs.find(SSRC);
389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (it == _csrcCNAMEs.end()) {
391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete it->second;
394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  _csrcCNAMEs.erase(it);
395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool
399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    For audio we use a fix 5 sec interval
403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
4055374dabd9f79f8f04c8b237a944771a46db25f27stefan@webrtc.org        technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
4065374dabd9f79f8f04c8b237a944771a46db25f27stefan@webrtc.org        that should be extremely rare
407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgFrom RFC 3550
410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MAX RTCP BW is 5% if the session BW
412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        A send report is approximately 65 bytes inc CNAME
4135374dabd9f79f8f04c8b237a944771a46db25f27stefan@webrtc.org        A receiver report is approximately 28 bytes
414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    The RECOMMENDED value for the reduced minimum in seconds is 360
416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      divided by the session bandwidth in kilobits/second.  This minimum
417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      is smaller than 5 seconds for bandwidths greater than 72 kb/s.
418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    If the participant has not yet sent an RTCP packet (the variable
420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      initial is true), the constant Tmin is set to 2.5 seconds, else it
421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      is set to 5 seconds.
422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    The interval between RTCP packets is varied randomly over the
424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      range [0.5,1.5] times the calculated interval to avoid unintended
425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      synchronization of all participants
426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if we send
428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    If the participant is a sender (we_sent true), the constant C is
429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      set to the average RTCP packet size (avg_rtcp_size) divided by 25%
430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      number of senders.
432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if we receive only
434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      If we_sent is not true, the constant C is set
435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      to the average RTCP packet size divided by 75% of the RTCP
436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      bandwidth.  The constant n is set to the number of receivers
437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (members - senders).  If the number of senders is greater than
438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      25%, senders and receivers are treated together.
439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    reconsideration NOT required for peer-to-peer
441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      "timer reconsideration" is
442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      employed.  This algorithm implements a simple back-off mechanism
443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      which causes users to hold back RTCP packet transmission if the
444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      group sizes are increasing.
445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      n = number of members
447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      C = avg_size/(rtcpBW/4)
448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   3. The deterministic calculated interval Td is set to max(Tmin, n*C).
450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   4. The calculated interval T is set to a number uniformly distributed
452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      between 0.5 and 1.5 times the deterministic calculated interval.
453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   5. The resulting value of T is divided by e-3/2=1.21828 to compensate
455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for the fact that the timer reconsideration algorithm converges to
456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      a value of the RTCP bandwidth below the intended average
457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org*/
458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
459b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    int64_t now = _clock->TimeInMilliseconds();
460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(_method == kRtcpOff)
464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return false;
466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(!_audio && sendKeyframeBeforeRTP)
469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // for video key-frames we want to send the RTCP before the large key-frame
471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // if we have a 100 ms margin
472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
4755374dabd9f79f8f04c8b237a944771a46db25f27stefan@webrtc.org    if(now >= _nextTimeToSendRTCP)
476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return true;
478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // wrap
482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return true;
483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
487b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orguint32_t
488b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgRTCPSender::LastSendReport( uint32_t& lastRTCPTime)
489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lastRTCPTime = _lastRTCPTime[0];
493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return _lastSendReport[0];
494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
496b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orguint32_t
497b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgRTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // This is only saved when we are the sender
502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if((_lastSendReport[0] == 0) || (sendReport == 0))
503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return 0; // will be ignored
505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else
506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            if( _lastSendReport[i] == sendReport)
510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                return _lastRTCPTime[i];
512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
518d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.orgbool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
519d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org                                      int64_t* time_ms) const {
520d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  CriticalSectionScoped lock(_criticalSectionRTCPSender);
521d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
522d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  if (last_xr_rr_.empty()) {
523d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org    return false;
524d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  }
525d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
526d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  if (it == last_xr_rr_.end()) {
527d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org    return false;
528d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  }
529d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  *time_ms = it->second;
530d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  return true;
531d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org}
532d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
5334a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.orgvoid RTCPSender::GetPacketTypeCounter(
5344a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org    RtcpPacketTypeCounter* packet_counter) const {
5354a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org  CriticalSectionScoped lock(_criticalSectionRTCPSender);
5364a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org  *packet_counter = packet_type_counter_;
5374a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org}
5384a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org
539a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.orgint32_t RTCPSender::AddExternalReportBlock(
540a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    uint32_t SSRC,
541a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    const RTCPReportBlock* reportBlock) {
542a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  CriticalSectionScoped lock(_criticalSectionRTCPSender);
543a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
544a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org}
545a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org
546a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.orgint32_t RTCPSender::AddReportBlock(
547a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    uint32_t SSRC,
548a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    std::map<uint32_t, RTCPReportBlock*>* report_blocks,
549a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    const RTCPReportBlock* reportBlock) {
55099681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org  assert(reportBlock);
551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
552a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
55399681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org    LOG(LS_WARNING) << "Too many report blocks.";
554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
556b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  std::map<uint32_t, RTCPReportBlock*>::iterator it =
557a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      report_blocks->find(SSRC);
558a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if (it != report_blocks->end()) {
559cf4441c9151afe2be8beb01d2ef49fd084d6c243stefan@webrtc.org    delete it->second;
560a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    report_blocks->erase(it);
561cf4441c9151afe2be8beb01d2ef49fd084d6c243stefan@webrtc.org  }
562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
564a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  (*report_blocks)[SSRC] = copyReportBlock;
565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
568a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.orgint32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped lock(_criticalSectionRTCPSender);
570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
571b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  std::map<uint32_t, RTCPReportBlock*>::iterator it =
572a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      external_report_blocks_.find(SSRC);
573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
574a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if (it == external_report_blocks_.end()) {
575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete it->second;
578a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  external_report_blocks_.erase(it);
579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
5824e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.orgint32_t RTCPSender::BuildSR(const FeedbackState& feedback_state,
5834e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                            uint8_t* rtcpbuffer,
5844e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                            int& pos,
5854e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                            uint32_t NTPsec,
5864e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                            uint32_t NTPfrac)
587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // sanity
589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(pos + 52 >= IP_PACKET_SIZE)
590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
59199681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org        LOG(LS_WARNING) << "Failed to build Sender Report.";
592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -2;
593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
594b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint32_t RTPtime;
595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
596b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint32_t posNumberOfReportBlocks = pos;
597b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0x80;
598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Sender report
600b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)200;
601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // shift old
605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        _lastSendReport[i+1] = _lastSendReport[i];
606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        _lastRTCPTime[i+1] =_lastRTCPTime[i];
607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
6099b5315258a9a931a4fb8b0806a79a4758a1ddc13stefan@webrtc.org    _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
61273ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org    // The timestamp of this RTCP packet should be estimated as the timestamp of
61373ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org    // the frame being captured at this moment. We are calculating that
61473ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org    // timestamp as the last frame's timestamp + the time since the last frame
61573ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org    // was captured.
6160cb22cf7e4f9531a0f218e27c8ea0d0620cf05d7pbos@webrtc.org    RTPtime = start_timestamp_ + last_rtp_timestamp_ +
6170cb22cf7e4f9531a0f218e27c8ea0d0620cf05d7pbos@webrtc.org              (_clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
6180cb22cf7e4f9531a0f218e27c8ea0d0620cf05d7pbos@webrtc.org                  (feedback_state.frequency_hz / 1000);
619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add sender data
621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Save  for our length field
622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;
623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;
624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add our own SSRC
6266aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // NTP
6296aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPsec);
630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
6316aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPfrac);
632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
6336aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, RTPtime);
634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //sender's packet count
6376aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
638442dbd4c3639676395c03d8a47562f650f2c378fpbos@webrtc.org                                      feedback_state.packets_sent);
639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //sender's octet count
6426aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
643442dbd4c3639676395c03d8a47562f650f2c378fpbos@webrtc.org                                      feedback_state.media_bytes_sent);
644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
646b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint8_t numberOfReportBlocks = 0;
647a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
648a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                                                  numberOfReportBlocks,
649a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                                                  NTPsec, NTPfrac);
650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(retVal < 0)
651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        //
653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return retVal ;
654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
655a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    pos = retVal;
656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
658b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint16_t len = uint16_t((pos/4) -1);
6596aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
664a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.orgint32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) {
665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  size_t lengthCname = strlen(_CNAME);
666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(lengthCname < RTCP_CNAME_SIZE);
667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // sanity
669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if(pos + 12 + lengthCname  >= IP_PACKET_SIZE) {
67099681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org    LOG(LS_WARNING) << "Failed to build SDEC.";
671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -2;
672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // SDEC Source Description
674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // We always need to add SDES CNAME
676b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
677b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = static_cast<uint8_t>(202);
678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // handle SDES length later on
680b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  uint32_t SDESLengthPos = pos;
681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  pos++;
682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  pos++;
683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Add our own SSRC
6856aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org  RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  pos += 4;
687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // CNAME = 1
689b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = static_cast<uint8_t>(1);
690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  //
692b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
694b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  uint16_t SDESLength = 10;
695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  pos += lengthCname;
698b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  SDESLength += (uint16_t)lengthCname;
699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
700b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  uint16_t padding = 0;
701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // We must have a zero field even if we have an even multiple of 4 bytes
702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((pos % 4) == 0) {
703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    padding++;
704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++]=0;
705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  while ((pos % 4) != 0) {
707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    padding++;
708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++]=0;
709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  SDESLength += padding;
711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
712b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
713b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      _csrcCNAMEs.begin();
714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for(; it != _csrcCNAMEs.end(); it++) {
716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    RTCPCnameInformation* cname = it->second;
717b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint32_t SSRC = it->first;
718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add SSRC
7206aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, SSRC);
721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // CNAME = 1
724b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++] = static_cast<uint8_t>(1);
725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    size_t length = strlen(cname->name);
727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    assert(length < RTCP_CNAME_SIZE);
728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
729b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]= static_cast<uint8_t>(length);
730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    SDESLength += 6;
731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(&rtcpbuffer[pos],cname->name, length);
733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += length;
735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    SDESLength += length;
736b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint16_t padding = 0;
737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // We must have a zero field even if we have an even multiple of 4 bytes
739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if((pos % 4) == 0){
740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      padding++;
741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      rtcpbuffer[pos++]=0;
742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    while((pos % 4) != 0){
744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      padding++;
745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      rtcpbuffer[pos++] = 0;
746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    SDESLength += padding;
748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // in 32-bit words minus one and we don't count the header
750b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  uint16_t buffer_length = (SDESLength / 4) - 1;
7516aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org  RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos, buffer_length);
752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
755b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
756b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgRTCPSender::BuildRR(uint8_t* rtcpbuffer,
757a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                    int& pos,
758b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                    const uint32_t NTPsec,
759a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                    const uint32_t NTPfrac)
760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // sanity one block
762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(pos + 32 >= IP_PACKET_SIZE)
763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -2;
765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
766b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint32_t posNumberOfReportBlocks = pos;
767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
768b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0x80;
769b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)201;
770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Save  for our length field
772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;
773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;
774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add our own SSRC
7766aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
779b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint8_t numberOfReportBlocks = 0;
780a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
781a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                                              numberOfReportBlocks,
782a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                                              NTPsec, NTPfrac);
783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(retVal < 0)
784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
785a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return pos;
786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
787a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    pos = retVal;
788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
790b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint16_t len = uint16_t((pos)/4 -1);
7916aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// From RFC 5450: Transmission Time Offsets in RTP Streams.
796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//        0                   1                   2                   3
797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//        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
798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//   hdr |V=2|P|    RC   |   PT=IJ=195   |             length            |
800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//       |                      inter-arrival jitter                     |
802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//       .                                                               .
804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//       .                                                               .
805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//       .                                                               .
806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//       |                      inter-arrival jitter                     |
807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  If present, this RTCP packet must be placed after a receiver report
810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  (inside a compound RTCP packet), and MUST have the same value for RC
811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  (reception report count) as the receiver report.
812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
813b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::BuildExtendedJitterReport(
815b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint8_t* rtcpbuffer,
816a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    int& pos,
817b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    const uint32_t jitterTransmissionTimeOffset)
818b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
819a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    if (external_report_blocks_.size() > 0)
820b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
82199681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org        // TODO(andresp): Remove external report blocks since they are not
82299681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org        // supported.
82399681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org        LOG(LS_ERROR) << "Handling of external report blocks not implemented.";
824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return 0;
825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // sanity
828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(pos + 8 >= IP_PACKET_SIZE)
829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -2;
831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // add picture loss indicator
833b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint8_t RC = 1;
834b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
835b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)195;
836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Used fixed length of 2
838b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0;
839b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)(1);
840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add inter-arrival jitter
8426aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
8436aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org                                      jitterTransmissionTimeOffset);
844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
845b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
848b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
849a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.orgRTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // sanity
852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(pos + 12 >= IP_PACKET_SIZE)
853b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
854b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -2;
855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
856b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // add picture loss indicator
857b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint8_t FMT = 1;
858b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
859b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)206;
860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //Used fixed length of 2
862b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0;
863b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)(2);
864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add our own SSRC
8666aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add the remote SSRC
8706aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
875b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
876a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                             int& pos,
877b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                             bool repeat) {
878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // sanity
879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if(pos + 20 >= IP_PACKET_SIZE)  {
880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -2;
881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (!repeat) {
883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _sequenceNumberFIR++;   // do not increase if repetition
884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // add full intra request indicator
887b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  uint8_t FMT = 4;
888b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
889b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = (uint8_t)206;
890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  //Length of 4
892b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = (uint8_t)0;
893b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = (uint8_t)(4);
894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Add our own SSRC
8966aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org  RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  pos += 4;
898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // RFC 5104     4.3.1.2.  Semantics
900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // SSRC of media source
901b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = (uint8_t)0;
902b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = (uint8_t)0;
903b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = (uint8_t)0;
904b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = (uint8_t)0;
905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Additional Feedback Control Information (FCI)
9076aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org  RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
908b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  pos += 4;
909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
910b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
911b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = (uint8_t)0;
912b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = (uint8_t)0;
913b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org  rtcpbuffer[pos++] = (uint8_t)0;
914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    0                   1                   2                   3
919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    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
920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   |            First        |        Number           | PictureID |
922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org*/
924b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
925a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.orgRTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID)
926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // sanity
928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(pos + 16 >= IP_PACKET_SIZE)
929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -2;
931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // add slice loss indicator
933b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint8_t FMT = 2;
934b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
935b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)206;
936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //Used fixed length of 3
938b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0;
939b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)(3);
940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
941b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add our own SSRC
9426aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add the remote SSRC
9466aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add first, number & picture ID 6 bits
950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // first  = 0, 13 - bits
951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // number = 0x1fff, 13 - bits only ones for now
952b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
9536aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, sliField);
954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
959b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    0                   1                   2                   3
960b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    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
961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   |      PB       |0| Payload Type|    Native RPSI bit string     |
963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   |   defined per codec          ...                | Padding (0) |
965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
966b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org*/
967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org*    Note: not generic made for VP8
969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org*/
970b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
971b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgRTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
972a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                     int& pos,
973b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                     const uint64_t pictureID,
974b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                     const uint8_t payloadType)
975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // sanity
977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(pos + 24 >= IP_PACKET_SIZE)
978b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -2;
980b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // add Reference Picture Selection Indication
982b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint8_t FMT = 3;
983b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
984b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)206;
985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // calc length
987b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint32_t bitsRequired = 7;
988b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint8_t bytesRequired = 1;
989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    while((pictureID>>bitsRequired) > 0)
990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bitsRequired += 7;
992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bytesRequired++;
993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
995b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint8_t size = 3;
996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(bytesRequired > 6)
997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        size = 5;
999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else if(bytesRequired > 2)
1000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1001b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        size = 4;
1002b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1003b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0;
1004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++]=size;
1005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add our own SSRC
10076aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
1008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
1009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add the remote SSRC
10116aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
1012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
1013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // calc padding length
1015b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint8_t paddingBytes = 4-((2+bytesRequired)%4);
1016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(paddingBytes == 4)
1017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        paddingBytes = 0;
1019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // add padding length in bits
1021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;
1023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // add payload type
1025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos] = payloadType;
1026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;
1027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // add picture ID
1029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for(int i = bytesRequired-1; i > 0; i--)
1030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1031b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
1032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos++;
1033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // add last byte of picture ID
1035b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
1036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;
1037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // add padding
1039b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for(int j = 0; j <paddingBytes; j++)
1040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        rtcpbuffer[pos] = 0;
1042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos++;
1043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1047b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
1048a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.orgRTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
1049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1050b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // sanity
1051b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1052b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -2;
1054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // add application layer feedback
1056b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint8_t FMT = 15;
1057b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1058b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)206;
1059b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1060b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0;
1061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add our own SSRC
10646aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
1065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
1066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Remote SSRC must be 0
10686aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, 0);
1069b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
1070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1071b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++]='R';
1072b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++]='E';
1073b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++]='M';
1074b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++]='B';
1075b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1076b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++] = _lengthRembSSRC;
1077b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // 6 bit Exp
1078b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // 18 bit mantissa
1079b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint8_t brExp = 0;
1080b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    for(uint32_t i=0; i<64; i++)
1081b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1082b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        if(_rembBitrate <= ((uint32_t)262143 << i))
1083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
1084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            brExp = i;
1085b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            break;
1086b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
1087b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1088b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    const uint32_t brMantissa = (_rembBitrate >> brExp);
1089b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1090b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1091b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)(brMantissa);
1092b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
109309da1a78127b1e5719daaf452f03d2012edad0dcstefan@webrtc.org    for (int i = 0; i < _lengthRembSSRC; i++)
10946aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    {
10956aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _rembSSRC[i]);
1096b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos += 4;
1097b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1098b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1099b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid
1102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::SetTargetBitrate(unsigned int target_bitrate)
1103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
1105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _tmmbr_Send = target_bitrate / 1000;
1106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11084e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.orgint32_t RTCPSender::BuildTMMBR(ModuleRtpRtcpImpl* rtp_rtcp_module,
11094e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                               uint8_t* rtcpbuffer,
11104e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                               int& pos) {
11114e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org    if (rtp_rtcp_module == NULL)
11124e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org      return -1;
1113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // If the sender is an owner of the TMMBN -> send TMMBR
1115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // get current bounding set from RTCP receiver
1118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    bool tmmbrOwner = false;
1119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // store in candidateSet, allocates one extra slot
1120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
1121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // since RTCPreceiver is not doing the reverse we should be fine
11254e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org    int32_t lengthOfBoundingSet =
11264e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org        rtp_rtcp_module->BoundingSet(tmmbrOwner, candidateSet);
1127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(lengthOfBoundingSet > 0)
1129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1130b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        for (int32_t i = 0; i < lengthOfBoundingSet; i++)
1131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
1132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                candidateSet->PacketOH(i) == _packetOH_Send)
1134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
1135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // do not send the same tuple
1136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                return 0;
1137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
1138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
1139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if(!tmmbrOwner)
1140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
1141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            // use received bounding set as candidate set
1142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            // add current tuple
1143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            candidateSet->SetEntry(lengthOfBoundingSet,
1144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                   _tmmbr_Send,
1145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                   _packetOH_Send,
1146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                   _SSRC);
1147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            int numCandidates = lengthOfBoundingSet+ 1;
1148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            // find bounding set
1150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            TMMBRSet* boundingSet = NULL;
1151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
1154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
1156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            if(!tmmbrOwner)
1157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
1158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // did not enter bounding set, no meaning to send this request
1159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                return 0;
1160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
1161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
1162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(_tmmbr_Send)
1165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // sanity
1167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if(pos + 20 >= IP_PACKET_SIZE)
1168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
1169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            return -2;
1170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
1171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // add TMMBR indicator
1172b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        uint8_t FMT = 3;
1173b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1174b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)205;
1175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        //Length of 4
1177b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)0;
1178b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)(4);
1179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // Add our own SSRC
11816aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org        RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
1182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos += 4;
1183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // RFC 5104     4.2.1.2.  Semantics
1185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // SSRC of media source
1187b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)0;
1188b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)0;
1189b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)0;
1190b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)0;
1191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // Additional Feedback Control Information (FCI)
11936aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org        RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
1194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos += 4;
1195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1196b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        uint32_t bitRate = _tmmbr_Send*1000;
1197b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        uint32_t mmbrExp = 0;
1198b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        for(uint32_t i=0;i<64;i++)
1199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
1200b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org            if(bitRate <= ((uint32_t)131071 << i))
1201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
1202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                mmbrExp = i;
1203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                break;
1204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
1205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
1206b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1208b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1209b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1210b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1211b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
1212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1216b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
1217a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.orgRTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
1218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(boundingSet == NULL)
1221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // sanity
1225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
1226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
122799681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org        LOG(LS_WARNING) << "Failed to build TMMBN.";
1228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -2;
1229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1230b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint8_t FMT = 4;
1231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // add TMMBN indicator
1232b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1233b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)205;
1234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //Add length later
1236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int posLength = pos;
1237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;
1238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;
1239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add our own SSRC
12416aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
1242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
1243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // RFC 5104     4.2.2.2.  Semantics
1245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // SSRC of media source
1247b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0;
1248b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0;
1249b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0;
1250b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0;
1251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Additional Feedback Control Information (FCI)
1253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int numBoundingSet = 0;
1254b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
1255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (boundingSet->Tmmbr(n) > 0)
1257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
1258b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org            uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
12596aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org            RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, tmmbrSSRC);
1260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            pos += 4;
1261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1262b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org            uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1263b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org            uint32_t mmbrExp = 0;
1264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            for(int i=0; i<64; i++)
1265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
1266b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                if(bitRate <=  ((uint32_t)131071 << i))
1267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                {
1268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    mmbrExp = i;
1269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    break;
1270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                }
1271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
1272b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org            uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1273b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org            uint32_t measuredOH = boundingSet->PacketOH(n);
1274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1275b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org            rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1276b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org            rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1277b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org            rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1278b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org            rtcpbuffer[pos++]=(uint8_t)(measuredOH);
1279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            numBoundingSet++;
1280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
1281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1282b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint16_t length= (uint16_t)(2+2*numBoundingSet);
1283b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1284b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[posLength]=(uint8_t)(length);
1285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1288b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
1289a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.orgRTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
1290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // sanity
1292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(_appData == NULL)
1293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
129499681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org        LOG(LS_WARNING) << "Failed to build app specific.";
1295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
129999681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org        LOG(LS_WARNING) << "Failed to build app specific.";
1300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -2;
1301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1302b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
1303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add APP ID
1305b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)204;
1306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1307b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1308b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)(length>>8);
1309b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)(length);
1310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add our own SSRC
13126aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
1313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
1314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add our application name
13166aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _appName);
1317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
1318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add the data
1320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(rtcpbuffer +pos, _appData,_appLength);
1321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += _appLength;
1322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1325b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
1326b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgRTCPSender::BuildNACK(uint8_t* rtcpbuffer,
1327a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                      int& pos,
1328b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                      const int32_t nackSize,
1329b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                      const uint16_t* nackList,
1330dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com                      std::string* nackString)
1331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // sanity
1333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(pos + 16 >= IP_PACKET_SIZE)
1334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
133599681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org        LOG(LS_WARNING) << "Failed to build NACK.";
1336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -2;
1337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1339b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    // int size, uint16_t* nackList
1340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // add nack list
1341b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint8_t FMT = 1;
1342b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1343b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)205;
1344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1345b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t) 0;
1346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int nackSizePos = pos;
1347b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
1348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add our own SSRC
13506aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
1351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
1352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add the remote SSRC
13546aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
1355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
1356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1357dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    NACKStringBuilder stringBuilder;
1358bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org    // Build NACK bitmasks and write them to the RTCP message.
1359bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org    // The nack list should be sorted and not contain duplicates if one
1360bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org    // wants to build the smallest rtcp nack packet.
1361bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org    int numOfNackFields = 0;
1362bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org    int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1363bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org                                      (IP_PACKET_SIZE - pos) / 4);
1364bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org    int i = 0;
1365bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org    while (i < nackSize && numOfNackFields < maxNackFields) {
1366bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org      stringBuilder.PushNACK(nackList[i]);
1367bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org      uint16_t nack = nackList[i++];
1368bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org      uint16_t bitmask = 0;
1369bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org      while (i < nackSize) {
1370bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org        int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1371bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org        if (shift >= 0 && shift <= 15) {
1372bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org          stringBuilder.PushNACK(nackList[i]);
1373bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org          bitmask |= (1 << shift);
1374bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org          ++i;
1375bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org        } else {
1376bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org          break;
1377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
1378bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org      }
1379bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org      // Write the sequence number and the bitmask to the packet.
1380bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org      assert(pos + 4 < IP_PACKET_SIZE);
13816aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
1382bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org      pos += 2;
13836aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
1384bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org      pos += 2;
1385bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org      numOfNackFields++;
1386bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org    }
1387bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org    if (i != nackSize) {
138899681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org      LOG(LS_WARNING) << "Nack list to large for one packet.";
1389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1390bda02e4a2e5a01cbd41fa0f0e5ad843d304404ccandresp@webrtc.org    rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
1391dded206d3c7f1b55ada0b36b84be80d987fd88c4edjee@google.com    *nackString = stringBuilder.GetResult();
1392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1395b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
1396a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.orgRTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
1397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // sanity
1399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(pos + 8 >= IP_PACKET_SIZE)
1400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -2;
1402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(_includeCSRCs)
1404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // Add a bye packet
1406b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs;  // number of SSRC+CSRCs
1407b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)203;
1408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // length
1410b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)0;
1411b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
1412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // Add our own SSRC
14146aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org        RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
1415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos += 4;
1416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // add CSRCs
1418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        for(int i = 0; i < _CSRCs; i++)
1419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
14206aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org          RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _CSRC[i]);
1421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            pos += 4;
1422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
1423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else
1424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // Add a bye packet
1426b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)0x80 + 1;  // number of SSRC+CSRCs
1427b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)203;
1428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // length
1430b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)0;
1431b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org        rtcpbuffer[pos++]=(uint8_t)1;
1432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // Add our own SSRC
14346aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org        RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
1435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos += 4;
1436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1440d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.orgint32_t RTCPSender::BuildReceiverReferenceTime(uint8_t* buffer,
1441d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org                                               int& pos,
1442d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org                                               uint32_t ntp_sec,
1443d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org                                               uint32_t ntp_frac) {
1444d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  const int kRrTimeBlockLength = 20;
1445d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  if (pos + kRrTimeBlockLength >= IP_PACKET_SIZE) {
1446d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org    return -2;
1447d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  }
1448d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
1449d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) {
1450d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org    last_xr_rr_.erase(last_xr_rr_.begin());
1451d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  }
1452d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
1453d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      RTCPUtility::MidNtp(ntp_sec, ntp_frac),
1454d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      Clock::NtpToMs(ntp_sec, ntp_frac)));
1455d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
1456d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  // Add XR header.
1457d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 0x80;
1458d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 207;
1459d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 0;  // XR packet length.
1460d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 4;  // XR packet length.
1461d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
1462d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  // Add our own SSRC.
14636aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org  RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
1464d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  pos += 4;
1465d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
1466d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //    0                   1                   2                   3
1467d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //    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
1468d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1469d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //   |     BT=4      |   reserved    |       block length = 2        |
1470d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1471d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //   |              NTP timestamp, most significant word             |
1472d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1473d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //   |             NTP timestamp, least significant word             |
1474d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1475d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
1476d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  // Add Receiver Reference Time Report block.
1477d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 4;  // BT.
1478d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 0;  // Reserved.
1479d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 0;  // Block length.
1480d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 2;  // Block length.
1481d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
1482d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  // NTP timestamp.
14836aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org  RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_sec);
1484d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  pos += 4;
14856aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org  RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_frac);
1486d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  pos += 4;
1487d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
1488d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  return 0;
1489d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org}
1490d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
1491d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.orgint32_t RTCPSender::BuildDlrr(uint8_t* buffer,
1492d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org                              int& pos,
1493d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org                              const RtcpReceiveTimeInfo& info) {
1494d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  const int kDlrrBlockLength = 24;
1495d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  if (pos + kDlrrBlockLength >= IP_PACKET_SIZE) {
1496d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org    return -2;
1497d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  }
1498d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
1499d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  // Add XR header.
1500d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 0x80;
1501d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 207;
1502d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 0;  // XR packet length.
1503d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 5;  // XR packet length.
1504d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
1505d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  // Add our own SSRC.
15066aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org  RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
1507d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  pos += 4;
1508d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
1509d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //   0                   1                   2                   3
1510d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //   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
1511d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1512d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //  |     BT=5      |   reserved    |         block length          |
1513d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1514d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //  |                 SSRC_1 (SSRC of first receiver)               | sub-
1515d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1516d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //  |                         last RR (LRR)                         |   1
1517d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1518d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //  |                   delay since last RR (DLRR)                  |
1519d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1520d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //  |                 SSRC_2 (SSRC of second receiver)              | sub-
1521d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1522d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  //  :                               ...                             :   2
1523d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
1524d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  // Add DLRR sub block.
1525d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 5;  // BT.
1526d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 0;  // Reserved.
1527d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 0;  // Block length.
1528d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  buffer[pos++] = 3;  // Block length.
1529d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
1530d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  // NTP timestamp.
15316aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org  RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.sourceSSRC);
1532d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  pos += 4;
15336aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org  RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.lastRR);
1534d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  pos += 4;
15356aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org  RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.delaySinceLastRR);
1536d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  pos += 4;
1537d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
1538d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  return 0;
1539d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org}
1540d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
1541b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
1542a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.orgRTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
1543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // sanity
1545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(pos + 44 >= IP_PACKET_SIZE)
1546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -2;
1548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add XR header
1551b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)0x80;
1552b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++]=(uint8_t)207;
1553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1554b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint32_t XRLengthPos = pos;
1555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // handle length later on
1557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;
1558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;
1559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add our own SSRC
15616aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
1562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
1563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add a VoIP metrics block
1565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++]=7;
1566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++]=0;
1567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++]=0;
1568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++]=8;
1569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Add the remote SSRC
15716aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
1572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 4;
1573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1579b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1580b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1581b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1582b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
1583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1584b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1585b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1586b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1587b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
1588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rtcpbuffer[pos++] = 0; // reserved
1601b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1602b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
1603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1604b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1605b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1606b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1607b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
1608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1609b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1610b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
1611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
16144e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.orgint32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
16154e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                             uint32_t packetTypeFlags,
16164e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                             int32_t nackSize,
16174e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                             const uint16_t* nackList,
16184e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                             bool repeat,
16194e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                             uint64_t pictureID) {
1620a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1621a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
1622a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    if(_method == kRtcpOff)
1623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
162499681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org        LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
1625a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1626a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    }
1627a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1628a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  uint8_t rtcp_buffer[IP_PACKET_SIZE];
16294e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org  int rtcp_length = PrepareRTCP(feedback_state,
16304e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                                packetTypeFlags,
16314e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                                nackSize,
16324e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                                nackList,
16334e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                                repeat,
16344e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                                pictureID,
16354e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                                rtcp_buffer,
16364e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                                IP_PACKET_SIZE);
1637a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if (rtcp_length < 0) {
1638a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    return -1;
1639a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1640a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  // Sanity don't send empty packets.
1641a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if (rtcp_length == 0)
1642a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1643a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      return -1;
1644a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1645a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  return SendToNetwork(rtcp_buffer, static_cast<uint16_t>(rtcp_length));
1646a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org}
1647c0976d247fedbe48d703f1ef3d5fb0fd70fdab93henrike@webrtc.org
16484e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.orgint RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
16494e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                            uint32_t packetTypeFlags,
16504e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                            int32_t nackSize,
16514e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                            const uint16_t* nackList,
16524e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                            bool repeat,
16534e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                            uint64_t pictureID,
16544e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                            uint8_t* rtcp_buffer,
16554e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                            int buffer_size) {
1656a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1657a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  // Collect the received information.
1658a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  uint32_t NTPsec = 0;
1659a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  uint32_t NTPfrac = 0;
1660a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  uint32_t jitterTransmissionOffset = 0;
1661a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  int position = 0;
1662c0976d247fedbe48d703f1ef3d5fb0fd70fdab93henrike@webrtc.org
1663a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  CriticalSectionScoped lock(_criticalSectionRTCPSender);
1664c0976d247fedbe48d703f1ef3d5fb0fd70fdab93henrike@webrtc.org
1665a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(_TMMBR )  // Attach TMMBR to send and receive reports.
1666a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1667a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      rtcpPacketTypeFlags |= kRtcpTmmbr;
1668a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1669a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(_appSend)
1670a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1671a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      rtcpPacketTypeFlags |= kRtcpApp;
1672a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      _appSend = false;
1673a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1674a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(_REMB && _sendREMB)
1675a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1676a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      // Always attach REMB to SR if that is configured. Note that REMB is
1677a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      // only sent on one of the RTP modules in the REMB group.
1678a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      rtcpPacketTypeFlags |= kRtcpRemb;
1679a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1680a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(_xrSendVoIPMetric)
1681a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1682a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1683a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      _xrSendVoIPMetric = false;
1684a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1685a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(_sendTMMBN)  // Set when having received a TMMBR.
1686a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1687a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      rtcpPacketTypeFlags |= kRtcpTmmbn;
1688a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      _sendTMMBN = false;
1689a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1690b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  if (rtcpPacketTypeFlags & kRtcpReport)
1691d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  {
1692b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      if (xrSendReceiverReferenceTimeEnabled_ && !_sending)
1693d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      {
1694d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org          rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
1695d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      }
1696d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      if (feedback_state.has_last_xr_rr)
1697d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      {
1698d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org          rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
1699d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      }
1700d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  }
1701a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(_method == kRtcpCompound)
1702a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1703a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if(_sending)
1704a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      {
1705a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          rtcpPacketTypeFlags |= kRtcpSr;
1706a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else
1707a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      {
1708a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          rtcpPacketTypeFlags |= kRtcpRr;
1709a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1710a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  } else if(_method == kRtcpNonCompound)
1711a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1712a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if(rtcpPacketTypeFlags & kRtcpReport)
1713a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      {
1714a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          if(_sending)
1715a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          {
1716a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org              rtcpPacketTypeFlags |= kRtcpSr;
1717a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          } else
1718a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          {
1719a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org              rtcpPacketTypeFlags |= kRtcpRr;
1720a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          }
1721a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1722a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1723a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if( rtcpPacketTypeFlags & kRtcpRr ||
1724a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      rtcpPacketTypeFlags & kRtcpSr)
1725a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1726a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      // generate next time to send a RTCP report
1727a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      // seeded from RTP constructor
1728a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      int32_t random = rand() % 1000;
1729a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1730a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org
1731a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if(_audio)
1732a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      {
1733a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1734a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org              (RTCP_INTERVAL_AUDIO_MS*random/1000);
1735a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }else
1736a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      {
1737a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1738a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          if(_sending)
1739a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          {
17404e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org            // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
17414e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org            uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
17424e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org            if (send_bitrate_kbit != 0)
17434e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org              minIntervalMs = 360000 / send_bitrate_kbit;
1744a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          }
1745a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1746a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          {
1747a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org              minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1748a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          }
1749a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1750a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1751a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1752a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1753c0976d247fedbe48d703f1ef3d5fb0fd70fdab93henrike@webrtc.org
1754a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  // If the data does not fit in the packet we fill it as much as possible.
1755a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  int32_t buildVal = 0;
1756a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org
1757a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  // We need to send our NTP even if we haven't received any reports.
1758a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  _clock->CurrentNtp(NTPsec, NTPfrac);
1759a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1760a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    StatisticianMap statisticians =
1761a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        receive_statistics_->GetActiveStatisticians();
1762a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    if (!statisticians.empty()) {
1763a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      StatisticianMap::const_iterator it;
1764a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      int i;
1765a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      for (it = statisticians.begin(), i = 0; it != statisticians.end();
1766a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org           ++it, ++i) {
1767a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        RTCPReportBlock report_block;
17684e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org        if (PrepareReport(
17694e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                feedback_state, it->second, &report_block, &NTPsec, &NTPfrac))
1770a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1771a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1772a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (_IJ && !statisticians.empty()) {
1773a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1774a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1775a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    }
1776a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1777c0976d247fedbe48d703f1ef3d5fb0fd70fdab93henrike@webrtc.org
1778a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(rtcpPacketTypeFlags & kRtcpSr)
1779a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
17804e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org    buildVal = BuildSR(feedback_state, rtcp_buffer, position, NTPsec, NTPfrac);
1781a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (buildVal == -1) {
1782a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1783a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else if (buildVal == -2) {
1784a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return position;
1785a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1786a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      buildVal = BuildSDEC(rtcp_buffer, position);
1787a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (buildVal == -1) {
1788a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1789a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else if (buildVal == -2) {
1790a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return position;
1791a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1792a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }else if(rtcpPacketTypeFlags & kRtcpRr)
1793a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1794a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1795a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (buildVal == -1) {
1796a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1797a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else if (buildVal == -2) {
1798a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return position;
1799a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1800a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      // only of set
1801a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if(_CNAME[0] != 0)
1802a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      {
1803a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          buildVal = BuildSDEC(rtcp_buffer, position);
1804a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          if (buildVal == -1) {
1805a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org            return -1;
1806a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org          }
1807a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1808a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1809a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1810a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1811a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      // If present, this RTCP packet must be placed after a
1812a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      // receiver report.
1813a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      buildVal = BuildExtendedJitterReport(rtcp_buffer,
1814a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                                           position,
1815a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                                           jitterTransmissionOffset);
1816a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (buildVal == -1) {
1817a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1818a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else if (buildVal == -2) {
1819a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return position;
1820a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1821a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1822a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(rtcpPacketTypeFlags & kRtcpPli)
1823a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1824a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      buildVal = BuildPLI(rtcp_buffer, position);
1825a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (buildVal == -1) {
1826a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1827a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else if (buildVal == -2) {
1828a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return position;
1829a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1830a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
18314a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org      ++packet_type_counter_.pli_packets;
18324a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org      TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC,
18334a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org                        packet_type_counter_.pli_packets);
1834a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1835a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(rtcpPacketTypeFlags & kRtcpFir)
1836a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1837a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      buildVal = BuildFIR(rtcp_buffer, position, repeat);
1838a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (buildVal == -1) {
1839a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1840a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else if (buildVal == -2) {
1841a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return position;
1842a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1843a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
18444a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org      ++packet_type_counter_.fir_packets;
1845a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
18464a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org                        packet_type_counter_.fir_packets);
1847a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1848a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(rtcpPacketTypeFlags & kRtcpSli)
1849a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1850a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1851a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (buildVal == -1) {
1852a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1853a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else if (buildVal == -2) {
1854a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return position;
1855a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1856a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1857a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(rtcpPacketTypeFlags & kRtcpRpsi)
1858a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
18594e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org      const int8_t payloadType = feedback_state.send_payload_type;
1860a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (payloadType == -1) {
1861a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1862a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1863a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1864a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                           (uint8_t)payloadType);
1865a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (buildVal == -1) {
1866a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1867a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else if (buildVal == -2) {
1868a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return position;
1869a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1870a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1871a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(rtcpPacketTypeFlags & kRtcpRemb)
1872a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1873a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      buildVal = BuildREMB(rtcp_buffer, position);
1874a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (buildVal == -1) {
1875a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1876a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else if (buildVal == -2) {
1877a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return position;
1878a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1879a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1880a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1881a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(rtcpPacketTypeFlags & kRtcpBye)
1882a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1883a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      buildVal = BuildBYE(rtcp_buffer, position);
1884a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (buildVal == -1) {
1885a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1886a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else if (buildVal == -2) {
1887a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return position;
1888a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1889a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1890a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(rtcpPacketTypeFlags & kRtcpApp)
1891a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1892a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      buildVal = BuildAPP(rtcp_buffer, position);
1893a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (buildVal == -1) {
1894a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1895a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else if (buildVal == -2) {
1896a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return position;
1897a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1898a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1899a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(rtcpPacketTypeFlags & kRtcpTmmbr)
1900a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
19014e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org      buildVal = BuildTMMBR(feedback_state.module, rtcp_buffer, position);
1902a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (buildVal == -1) {
1903a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1904a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else if (buildVal == -2) {
1905a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return position;
1906a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1907a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1908a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(rtcpPacketTypeFlags & kRtcpTmmbn)
1909a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1910a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      buildVal = BuildTMMBN(rtcp_buffer, position);
1911a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (buildVal == -1) {
1912a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1913a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else if (buildVal == -2) {
1914a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return position;
1915a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1916a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1917a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(rtcpPacketTypeFlags & kRtcpNack)
1918a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1919a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      std::string nackString;
1920a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
1921a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                           &nackString);
1922a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (buildVal == -1) {
1923a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1924a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else if (buildVal == -2) {
1925a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return position;
1926a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1927a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
1928a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                           "nacks", TRACE_STR_COPY(nackString.c_str()));
19294a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org      ++packet_type_counter_.nack_packets;
19304a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org      TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC,
19314a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org                        packet_type_counter_.nack_packets);
1932a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1933a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1934a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  {
1935a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      buildVal = BuildVoIPMetric(rtcp_buffer, position);
1936a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      if (buildVal == -1) {
1937a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return -1;
1938a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      } else if (buildVal == -2) {
1939a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org        return position;
1940a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      }
1941a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
1942d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  if (rtcpPacketTypeFlags & kRtcpXrReceiverReferenceTime)
1943d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  {
1944d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      buildVal = BuildReceiverReferenceTime(rtcp_buffer,
1945d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org                                            position,
1946d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org                                            NTPsec,
1947d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org                                            NTPfrac);
1948d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      if (buildVal == -1) {
1949d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org        return -1;
1950d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      } else if (buildVal == -2) {
1951d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org        return position;
1952d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      }
1953d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  }
1954d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  if (rtcpPacketTypeFlags & kRtcpXrDlrrReportBlock)
1955d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  {
1956d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      buildVal = BuildDlrr(rtcp_buffer, position, feedback_state.last_xr_rr);
1957d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      if (buildVal == -1) {
1958d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org        return -1;
1959d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      } else if (buildVal == -2) {
1960d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org        return position;
1961d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org      }
1962d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  }
1963a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  return position;
1964a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org}
1965c0976d247fedbe48d703f1ef3d5fb0fd70fdab93henrike@webrtc.org
1966a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.orgbool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
1967a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  return Status() == kRtcpCompound ||
1968a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      (rtcp_packet_type & kRtcpReport) ||
1969a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      (rtcp_packet_type & kRtcpSr) ||
1970a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      (rtcp_packet_type & kRtcpRr);
1971a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org}
1972c0976d247fedbe48d703f1ef3d5fb0fd70fdab93henrike@webrtc.org
19734e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.orgbool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
19744e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org                               StreamStatistician* statistician,
1975a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                               RTCPReportBlock* report_block,
1976a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org                               uint32_t* ntp_secs, uint32_t* ntp_frac) {
1977a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  // Do we have receive statistics to send?
19784f1f5fa55d803fc0b7f3fd4f6a25a0f84c4e3280sprang@webrtc.org  RtcpStatistics stats;
1979a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if (!statistician->GetStatistics(&stats, true))
1980a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    return false;
1981a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  report_block->fractionLost = stats.fraction_lost;
1982a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  report_block->cumulativeLost = stats.cumulative_lost;
1983a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  report_block->extendedHighSeqNum =
1984a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      stats.extended_max_sequence_number;
1985a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  report_block->jitter = stats.jitter;
1986a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org
1987a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  // get our NTP as late as possible to avoid a race
1988a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  _clock->CurrentNtp(*ntp_secs, *ntp_frac);
1989a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org
1990a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  // Delay since last received report
1991a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  uint32_t delaySinceLastReceivedSR = 0;
19924e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org  if ((feedback_state.last_rr_ntp_secs != 0) ||
19934e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org      (feedback_state.last_rr_ntp_frac != 0)) {
1994a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1995a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    uint32_t now=*ntp_secs&0x0000FFFF;
1996a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    now <<=16;
1997a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    now += (*ntp_frac&0xffff0000)>>16;
1998a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org
19994e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org    uint32_t receiveTime = feedback_state.last_rr_ntp_secs&0x0000FFFF;
2000a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    receiveTime <<=16;
20014e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org    receiveTime += (feedback_state.last_rr_ntp_frac&0xffff0000)>>16;
2002a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org
2003a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    delaySinceLastReceivedSR = now-receiveTime;
2004a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
2005a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  report_block->delaySinceLastSR = delaySinceLastReceivedSR;
20064e7777bf0337ddb74b0cc8e5a5f3619d8dd770cfpbos@webrtc.org  report_block->lastSR = feedback_state.remote_sr;
2007a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  return true;
2008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2010b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
2011b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgRTCPSender::SendToNetwork(const uint8_t* dataBuffer,
2012b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                          const uint16_t length)
2013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionTransport);
2015b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(_cbTransport)
2016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
2018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
2019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            return 0;
2020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
2021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
2023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2025b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
2026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::SetCSRCStatus(const bool include)
2027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
20280cb22cf7e4f9531a0f218e27c8ea0d0620cf05d7pbos@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
2029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _includeCSRCs = include;
2030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
2031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2033b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
2034b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgRTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
2035b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                    const uint8_t arrLength)
2036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
203799681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org    assert(arrLength <= kRtpCsrcSize);
2038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
2039b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for(int i = 0; i < arrLength;i++)
2041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        _CSRC[i] = arrOfCSRC[i];
2043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _CSRCs = arrLength;
2045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
2046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2048b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
2049b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgRTCPSender::SetApplicationSpecificData(const uint8_t subType,
2050b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                                       const uint32_t name,
2051b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                                       const uint8_t* data,
2052b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                                       const uint16_t length)
2053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(length %4 != 0)
2055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
205699681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org        LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
2057b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
2058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2059b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
2060b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(_appData)
2062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        delete [] _appData;
2064b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _appSend = true;
2067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _appSubType = subType;
2068b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _appName = name;
2069b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    _appData = new uint8_t[length];
2070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _appLength = length;
2071b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(_appData, data, length);
2072b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
2073b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2074b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2075b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
2076b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2077b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2078b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
2079b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2080b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2081b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _xrSendVoIPMetric = true;
2082b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
2083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2085d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.orgvoid RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
2086d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  CriticalSectionScoped lock(_criticalSectionRTCPSender);
2087d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org  xrSendReceiverReferenceTimeEnabled_ = enable;
2088d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org}
2089d6da239905c84110a7c90789df70238afd0f64b6asapersson@webrtc.org
20903dc7ff30185a2d7a597acb69183fca73bd1004d8asapersson@webrtc.orgbool RTCPSender::RtcpXrReceiverReferenceTime() const {
20913dc7ff30185a2d7a597acb69183fca73bd1004d8asapersson@webrtc.org  CriticalSectionScoped lock(_criticalSectionRTCPSender);
20923dc7ff30185a2d7a597acb69183fca73bd1004d8asapersson@webrtc.org  return xrSendReceiverReferenceTimeEnabled_;
20933dc7ff30185a2d7a597acb69183fca73bd1004d8asapersson@webrtc.org}
20943dc7ff30185a2d7a597acb69183fca73bd1004d8asapersson@webrtc.org
2095b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// called under critsect _criticalSectionRTCPSender
2096a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.orgint32_t RTCPSender::WriteAllReportBlocksToBuffer(
2097a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    uint8_t* rtcpbuffer,
2098a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    int pos,
2099a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    uint8_t& numberOfReportBlocks,
2100a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    const uint32_t NTPsec,
2101a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    const uint32_t NTPfrac) {
2102a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  numberOfReportBlocks = external_report_blocks_.size();
2103a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  numberOfReportBlocks += internal_report_blocks_.size();
2104a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
210599681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org    LOG(LS_WARNING) << "Can't fit all report blocks.";
2106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
2107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
2108a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2109a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  while (!internal_report_blocks_.empty()) {
2110a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    delete internal_report_blocks_.begin()->second;
2111a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    internal_report_blocks_.erase(internal_report_blocks_.begin());
2112a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  }
2113a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2114a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  return pos;
2115a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org}
2116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2117a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.orgint32_t RTCPSender::WriteReportBlocksToBuffer(
2118a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    uint8_t* rtcpbuffer,
2119a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    int32_t position,
2120a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org    const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2121a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2122a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      report_blocks.begin();
2123a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  for (; it != report_blocks.end(); it++) {
2124b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org    uint32_t remoteSSRC = it->first;
2125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    RTCPReportBlock* reportBlock = it->second;
2126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (reportBlock) {
2127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // Remote SSRC
21286aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position, remoteSSRC);
2129a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      position += 4;
2130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // fraction lost
2132a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      rtcpbuffer[position++] = reportBlock->fractionLost;
2133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // cumulative loss
21356aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      RtpUtility::AssignUWord24ToBuffer(rtcpbuffer + position,
21366aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org                                        reportBlock->cumulativeLost);
2137a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      position += 3;
2138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // extended highest seq_no, contain the highest sequence number received
21406aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
21416aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org                                        reportBlock->extendedHighSeqNum);
2142a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      position += 4;
2143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2144a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      // Jitter
21456aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
21466aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org                                        reportBlock->jitter);
2147a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      position += 4;
2148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
21496aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
21506aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org                                        reportBlock->lastSR);
2151a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      position += 4;
2152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
21536aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
21546aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org                                        reportBlock->delaySinceLastSR);
2155a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org      position += 4;
2156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
2158a20e2d4c9ae860db62de6e304bfdf517c049ec3dstefan@webrtc.org  return position;
2159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// no callbacks allowed inside this function
2162b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t
2163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
2164b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org                     const uint32_t maxBitrateKbit)
2165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(_criticalSectionRTCPSender);
2167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        _sendTMMBN = true;
2171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return 0;
2172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
2174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
21753b89e10f31160da35b408fd00cb8f89d2b08862dpbos@webrtc.org}  // namespace webrtc
2176