blob: 2cf7e1cbc8ad4e94d8bccc60d27721df9690c54e [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> // assert
14#include <stdlib.h> // rand
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000015#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000017#include <algorithm> // min
18
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000019#include "webrtc/common_types.h"
20#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
21#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000022#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000023#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000024
niklase@google.com470e71d2011-07-07 08:21:25 +000025namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000026
27using RTCPUtility::RTCPCnameInformation;
28
edjee@google.com79b02892013-04-04 19:43:34 +000029NACKStringBuilder::NACKStringBuilder() :
30 _stream(""), _count(0), _consecutive(false)
31{
32 // Empty.
33}
34
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000035NACKStringBuilder::~NACKStringBuilder() {}
36
pbos@webrtc.org2f446732013-04-08 11:08:41 +000037void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000038{
39 if (_count == 0)
40 {
41 _stream << nack;
42 } else if (nack == _prevNack + 1)
43 {
44 _consecutive = true;
45 } else
46 {
47 if (_consecutive)
48 {
49 _stream << "-" << _prevNack;
50 _consecutive = false;
51 }
52 _stream << "," << nack;
53 }
54 _count++;
55 _prevNack = nack;
56}
57
58std::string NACKStringBuilder::GetResult()
59{
60 if (_consecutive)
61 {
62 _stream << "-" << _prevNack;
63 _consecutive = false;
64 }
65 return _stream.str();
66}
67
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000068RTCPSender::FeedbackState::FeedbackState(ModuleRtpRtcpImpl* module)
69 : send_payload_type(module->SendPayloadType()),
70 frequency_hz(module->CurrentSendFrequencyHz()),
71 packet_count_sent(module->PacketCountSent()),
72 byte_count_sent(module->ByteCountSent()),
73 module(module) {
74 uint32_t last_ntp_secs = 0, last_ntp_frac = 0, last_remote_sr = 0;
75 module->LastReceivedNTP(last_ntp_secs, last_ntp_frac, last_remote_sr);
76 last_rr_ntp_secs = last_ntp_secs;
77 last_rr_ntp_frac = last_ntp_frac;
78 remote_sr = last_remote_sr;
79
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000080 has_last_xr_rr = module->LastReceivedXrReferenceTimeInfo(&last_xr_rr);
81
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000082 uint32_t send_bitrate = 0, tmp;
83 module->BitrateSent(&send_bitrate, &tmp, &tmp, &tmp);
84 this->send_bitrate = send_bitrate;
85}
86
87RTCPSender::FeedbackState::FeedbackState()
88 : send_payload_type(0),
89 frequency_hz(0),
90 packet_count_sent(0),
91 byte_count_sent(0),
92 send_bitrate(0),
93 last_rr_ntp_secs(0),
94 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000095 remote_sr(0),
96 has_last_xr_rr(false) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000097
pbos@webrtc.org2f446732013-04-08 11:08:41 +000098RTCPSender::RTCPSender(const int32_t id,
niklase@google.com470e71d2011-07-07 08:21:25 +000099 const bool audio,
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000100 Clock* clock,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000101 ReceiveStatistics* receive_statistics) :
niklase@google.com470e71d2011-07-07 08:21:25 +0000102 _id(id),
103 _audio(audio),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000104 _clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +0000105 _method(kRtcpOff),
henrike@webrtc.org65573f22011-12-13 19:17:27 +0000106 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +0000107 _cbTransport(NULL),
108
henrike@webrtc.org65573f22011-12-13 19:17:27 +0000109 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +0000110 _usingNack(false),
111 _sending(false),
112 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000113 _REMB(false),
114 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000115 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000116 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000117 _nextTimeToSendRTCP(0),
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000118 start_timestamp_(0),
119 last_rtp_timestamp_(0),
120 last_frame_capture_time_ms_(-1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000121 _SSRC(0),
122 _remoteSSRC(0),
123 _CNAME(),
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000124 receive_statistics_(receive_statistics),
125 internal_report_blocks_(),
126 external_report_blocks_(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000127 _csrcCNAMEs(),
128
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000129 _cameraDelayMS(0),
130
niklase@google.com470e71d2011-07-07 08:21:25 +0000131 _lastSendReport(),
132 _lastRTCPTime(),
133
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000134 last_xr_rr_(),
135
niklase@google.com470e71d2011-07-07 08:21:25 +0000136 _CSRCs(0),
137 _CSRC(),
138 _includeCSRCs(true),
139
140 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000141
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000142 _lengthRembSSRC(0),
143 _sizeRembSSRC(0),
144 _rembSSRC(NULL),
145 _rembBitrate(0),
146
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000147 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000148 _tmmbr_Send(0),
149 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000150
151 _appSend(false),
152 _appSubType(0),
153 _appName(),
154 _appData(NULL),
155 _appLength(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000156
157 xrSendReceiverReferenceTimeEnabled_(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000158 _xrSendVoIPMetric(false),
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000159 _xrVoIPMetric()
niklase@google.com470e71d2011-07-07 08:21:25 +0000160{
161 memset(_CNAME, 0, sizeof(_CNAME));
162 memset(_lastSendReport, 0, sizeof(_lastSendReport));
163 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
niklase@google.com470e71d2011-07-07 08:21:25 +0000164}
165
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000166RTCPSender::~RTCPSender() {
167 delete [] _rembSSRC;
168 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000169
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000170 while (!internal_report_blocks_.empty()) {
171 delete internal_report_blocks_.begin()->second;
172 internal_report_blocks_.erase(internal_report_blocks_.begin());
173 }
174 while (!external_report_blocks_.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000175 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000176 external_report_blocks_.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000177 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000178 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000179 }
180 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000181 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000182 _csrcCNAMEs.begin();
183 delete it->second;
184 _csrcCNAMEs.erase(it);
185 }
186 delete _criticalSectionTransport;
187 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000188}
189
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000190int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000191RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
192{
193 CriticalSectionScoped lock(_criticalSectionTransport);
194 _cbTransport = outgoingTransport;
195 return 0;
196}
197
198RTCPMethod
199RTCPSender::Status() const
200{
201 CriticalSectionScoped lock(_criticalSectionRTCPSender);
202 return _method;
203}
204
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000205int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000206RTCPSender::SetRTCPStatus(const RTCPMethod method)
207{
208 CriticalSectionScoped lock(_criticalSectionRTCPSender);
209 if(method != kRtcpOff)
210 {
211 if(_audio)
212 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000213 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000214 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000215 } else
216 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000217 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000218 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000219 }
220 }
221 _method = method;
222 return 0;
223}
224
225bool
226RTCPSender::Sending() const
227{
228 CriticalSectionScoped lock(_criticalSectionRTCPSender);
229 return _sending;
230}
231
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000232int32_t
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000233RTCPSender::SetSendingStatus(const FeedbackState& feedback_state, bool sending)
niklase@google.com470e71d2011-07-07 08:21:25 +0000234{
235 bool sendRTCPBye = false;
236 {
237 CriticalSectionScoped lock(_criticalSectionRTCPSender);
238
239 if(_method != kRtcpOff)
240 {
241 if(sending == false && _sending == true)
242 {
243 // Trigger RTCP bye
244 sendRTCPBye = true;
245 }
246 }
247 _sending = sending;
248 }
249 if(sendRTCPBye)
250 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000251 return SendRTCP(feedback_state, kRtcpBye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000252 }
253 return 0;
254}
255
256bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000257RTCPSender::REMB() const
258{
259 CriticalSectionScoped lock(_criticalSectionRTCPSender);
260 return _REMB;
261}
262
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000263int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000264RTCPSender::SetREMBStatus(const bool enable)
265{
266 CriticalSectionScoped lock(_criticalSectionRTCPSender);
267 _REMB = enable;
268 return 0;
269}
270
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000271int32_t
272RTCPSender::SetREMBData(const uint32_t bitrate,
273 const uint8_t numberOfSSRC,
274 const uint32_t* SSRC)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000275{
276 CriticalSectionScoped lock(_criticalSectionRTCPSender);
277 _rembBitrate = bitrate;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000278
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000279 if(_sizeRembSSRC < numberOfSSRC)
280 {
281 delete [] _rembSSRC;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000282 _rembSSRC = new uint32_t[numberOfSSRC];
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000283 _sizeRembSSRC = numberOfSSRC;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000284 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000285
286 _lengthRembSSRC = numberOfSSRC;
287 for (int i = 0; i < numberOfSSRC; i++)
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000288 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000289 _rembSSRC[i] = SSRC[i];
290 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000291 _sendREMB = true;
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000292 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
293 // throttled by the caller.
294 _nextTimeToSendRTCP = _clock->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000295 return 0;
296}
297
298bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000299RTCPSender::TMMBR() const
300{
301 CriticalSectionScoped lock(_criticalSectionRTCPSender);
302 return _TMMBR;
303}
304
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000305int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000306RTCPSender::SetTMMBRStatus(const bool enable)
307{
308 CriticalSectionScoped lock(_criticalSectionRTCPSender);
309 _TMMBR = enable;
310 return 0;
311}
312
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000313bool
314RTCPSender::IJ() const
315{
316 CriticalSectionScoped lock(_criticalSectionRTCPSender);
317 return _IJ;
318}
319
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000320int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000321RTCPSender::SetIJStatus(const bool enable)
322{
323 CriticalSectionScoped lock(_criticalSectionRTCPSender);
324 _IJ = enable;
325 return 0;
326}
327
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000328void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
pbos@webrtc.org180e5162014-07-11 15:36:26 +0000329 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000330 start_timestamp_ = start_timestamp;
331}
332
333void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
334 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000335 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000336 last_rtp_timestamp_ = rtp_timestamp;
337 if (capture_time_ms < 0) {
338 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000339 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000340 } else {
341 last_frame_capture_time_ms_ = capture_time_ms;
342 }
343}
344
niklase@google.com470e71d2011-07-07 08:21:25 +0000345void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000346RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000347{
348 CriticalSectionScoped lock(_criticalSectionRTCPSender);
349
350 if(_SSRC != 0)
351 {
352 // not first SetSSRC, probably due to a collision
353 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000354 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000355 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000356 }
357 _SSRC = ssrc;
358}
359
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000360void RTCPSender::SetRemoteSSRC(uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000361{
362 CriticalSectionScoped lock(_criticalSectionRTCPSender);
363 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000364}
365
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000366int32_t
367RTCPSender::SetCameraDelay(const int32_t delayMS)
368{
369 CriticalSectionScoped lock(_criticalSectionRTCPSender);
370 if(delayMS > 1000 || delayMS < -1000)
371 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000372 LOG(LS_WARNING) << "Delay can't be larger than 1 second: "
373 << delayMS << " ms";
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000374 return -1;
375 }
376 _cameraDelayMS = delayMS;
377 return 0;
378}
379
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000380int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000381 if (!cName)
382 return -1;
383
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000384 CriticalSectionScoped lock(_criticalSectionRTCPSender);
385 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
386 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
387 return 0;
388}
389
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000390int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
391 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000392 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000393 CriticalSectionScoped lock(_criticalSectionRTCPSender);
394 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
395 return -1;
396 }
397 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000398 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
399 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000400 _csrcCNAMEs[SSRC] = ptr;
401 return 0;
402}
403
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000404int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000405 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000406 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000407 _csrcCNAMEs.find(SSRC);
408
409 if (it == _csrcCNAMEs.end()) {
410 return -1;
411 }
412 delete it->second;
413 _csrcCNAMEs.erase(it);
414 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000415}
416
417bool
418RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
419{
420/*
421 For audio we use a fix 5 sec interval
422
423 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000424 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
425 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000426
427
428From RFC 3550
429
430 MAX RTCP BW is 5% if the session BW
431 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000432 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000433
434 The RECOMMENDED value for the reduced minimum in seconds is 360
435 divided by the session bandwidth in kilobits/second. This minimum
436 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
437
438 If the participant has not yet sent an RTCP packet (the variable
439 initial is true), the constant Tmin is set to 2.5 seconds, else it
440 is set to 5 seconds.
441
442 The interval between RTCP packets is varied randomly over the
443 range [0.5,1.5] times the calculated interval to avoid unintended
444 synchronization of all participants
445
446 if we send
447 If the participant is a sender (we_sent true), the constant C is
448 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
449 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
450 number of senders.
451
452 if we receive only
453 If we_sent is not true, the constant C is set
454 to the average RTCP packet size divided by 75% of the RTCP
455 bandwidth. The constant n is set to the number of receivers
456 (members - senders). If the number of senders is greater than
457 25%, senders and receivers are treated together.
458
459 reconsideration NOT required for peer-to-peer
460 "timer reconsideration" is
461 employed. This algorithm implements a simple back-off mechanism
462 which causes users to hold back RTCP packet transmission if the
463 group sizes are increasing.
464
465 n = number of members
466 C = avg_size/(rtcpBW/4)
467
468 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
469
470 4. The calculated interval T is set to a number uniformly distributed
471 between 0.5 and 1.5 times the deterministic calculated interval.
472
473 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
474 for the fact that the timer reconsideration algorithm converges to
475 a value of the RTCP bandwidth below the intended average
476*/
477
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000478 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000479
480 CriticalSectionScoped lock(_criticalSectionRTCPSender);
481
niklase@google.com470e71d2011-07-07 08:21:25 +0000482 if(_method == kRtcpOff)
483 {
484 return false;
485 }
486
niklase@google.com470e71d2011-07-07 08:21:25 +0000487 if(!_audio && sendKeyframeBeforeRTP)
488 {
489 // for video key-frames we want to send the RTCP before the large key-frame
490 // if we have a 100 ms margin
491 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
492 }
493
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000494 if(now >= _nextTimeToSendRTCP)
niklase@google.com470e71d2011-07-07 08:21:25 +0000495 {
496 return true;
497
498 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
499 {
500 // wrap
501 return true;
502 }
503 return false;
504}
505
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000506uint32_t
507RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000508{
509 CriticalSectionScoped lock(_criticalSectionRTCPSender);
510
511 lastRTCPTime = _lastRTCPTime[0];
512 return _lastSendReport[0];
513}
514
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000515uint32_t
516RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000517{
518 CriticalSectionScoped lock(_criticalSectionRTCPSender);
519
520 // This is only saved when we are the sender
521 if((_lastSendReport[0] == 0) || (sendReport == 0))
522 {
523 return 0; // will be ignored
524 } else
525 {
526 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
527 {
528 if( _lastSendReport[i] == sendReport)
529 {
530 return _lastRTCPTime[i];
531 }
532 }
533 }
534 return 0;
535}
536
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000537bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
538 int64_t* time_ms) const {
539 CriticalSectionScoped lock(_criticalSectionRTCPSender);
540
541 if (last_xr_rr_.empty()) {
542 return false;
543 }
544 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
545 if (it == last_xr_rr_.end()) {
546 return false;
547 }
548 *time_ms = it->second;
549 return true;
550}
551
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000552void RTCPSender::GetPacketTypeCounter(
553 RtcpPacketTypeCounter* packet_counter) const {
554 CriticalSectionScoped lock(_criticalSectionRTCPSender);
555 *packet_counter = packet_type_counter_;
556}
557
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000558int32_t RTCPSender::AddExternalReportBlock(
559 uint32_t SSRC,
560 const RTCPReportBlock* reportBlock) {
561 CriticalSectionScoped lock(_criticalSectionRTCPSender);
562 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
563}
564
565int32_t RTCPSender::AddReportBlock(
566 uint32_t SSRC,
567 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
568 const RTCPReportBlock* reportBlock) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000569 assert(reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000570
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000571 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000572 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000573 return -1;
574 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000575 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000576 report_blocks->find(SSRC);
577 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000578 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000579 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000580 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000581 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
582 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000583 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000584 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000585}
586
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000587int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000588 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000589
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000590 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000591 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000592
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000593 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000594 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000595 }
596 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000597 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000598 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000599}
600
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000601int32_t RTCPSender::BuildSR(const FeedbackState& feedback_state,
602 uint8_t* rtcpbuffer,
603 int& pos,
604 uint32_t NTPsec,
605 uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000606{
607 // sanity
608 if(pos + 52 >= IP_PACKET_SIZE)
609 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000610 LOG(LS_WARNING) << "Failed to build Sender Report.";
niklase@google.com470e71d2011-07-07 08:21:25 +0000611 return -2;
612 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000613 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000614
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000615 uint32_t posNumberOfReportBlocks = pos;
616 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000617
618 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000619 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000620
621 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
622 {
623 // shift old
624 _lastSendReport[i+1] = _lastSendReport[i];
625 _lastRTCPTime[i+1] =_lastRTCPTime[i];
626 }
627
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000628 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000629 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000630
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000631 // The timestamp of this RTCP packet should be estimated as the timestamp of
632 // the frame being captured at this moment. We are calculating that
633 // timestamp as the last frame's timestamp + the time since the last frame
634 // was captured.
pbos@webrtc.org180e5162014-07-11 15:36:26 +0000635 RTPtime = start_timestamp_ + last_rtp_timestamp_ +
636 (_clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
637 (feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000638
639 // Add sender data
640 // Save for our length field
641 pos++;
642 pos++;
643
644 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000645 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000646 pos += 4;
647 // NTP
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000648 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000649 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000650 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000651 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000652 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, RTPtime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000653 pos += 4;
654
655 //sender's packet count
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000656 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
657 feedback_state.packet_count_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000658 pos += 4;
659
660 //sender's octet count
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000661 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
662 feedback_state.byte_count_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000663 pos += 4;
664
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000665 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000666 int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
667 numberOfReportBlocks,
668 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000669 if(retVal < 0)
670 {
671 //
672 return retVal ;
673 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000674 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000675 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
676
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000677 uint16_t len = uint16_t((pos/4) -1);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000678 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000679 return 0;
680}
681
682
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000683int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000684 size_t lengthCname = strlen(_CNAME);
685 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000686
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000687 // sanity
688 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000689 LOG(LS_WARNING) << "Failed to build SDEC.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000690 return -2;
691 }
692 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000693
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000694 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000695 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
696 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000697
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000698 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000699 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000700 pos++;
701 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000702
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000703 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000704 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000705 pos += 4;
706
707 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000708 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000709
710 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000711 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000712
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000713 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000714
715 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
716 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000717 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000718
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000719 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000720 // We must have a zero field even if we have an even multiple of 4 bytes
721 if ((pos % 4) == 0) {
722 padding++;
723 rtcpbuffer[pos++]=0;
724 }
725 while ((pos % 4) != 0) {
726 padding++;
727 rtcpbuffer[pos++]=0;
728 }
729 SDESLength += padding;
730
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000731 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000732 _csrcCNAMEs.begin();
733
734 for(; it != _csrcCNAMEs.end(); it++) {
735 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000736 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000737
738 // Add SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000739 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000740 pos += 4;
741
742 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000743 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000744
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000745 size_t length = strlen(cname->name);
746 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000747
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000748 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000749 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000750
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000751 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000752
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000753 pos += length;
754 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000755 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000756
757 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000758 if((pos % 4) == 0){
759 padding++;
760 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000761 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000762 while((pos % 4) != 0){
763 padding++;
764 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000765 }
766 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000767 }
768 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000769 uint16_t buffer_length = (SDESLength / 4) - 1;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000770 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos, buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000771 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000772}
773
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000774int32_t
775RTCPSender::BuildRR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000776 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000777 const uint32_t NTPsec,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000778 const uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000779{
780 // sanity one block
781 if(pos + 32 >= IP_PACKET_SIZE)
782 {
783 return -2;
784 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000785 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000786
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000787 rtcpbuffer[pos++]=(uint8_t)0x80;
788 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000789
790 // Save for our length field
791 pos++;
792 pos++;
793
794 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000795 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000796 pos += 4;
797
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000798 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000799 int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
800 numberOfReportBlocks,
801 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000802 if(retVal < 0)
803 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000804 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000805 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000806 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000807 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
808
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000809 uint16_t len = uint16_t((pos)/4 -1);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000810 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000811 return 0;
812}
813
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000814// From RFC 5450: Transmission Time Offsets in RTP Streams.
815// 0 1 2 3
816// 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
817// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
818// hdr |V=2|P| RC | PT=IJ=195 | length |
819// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
820// | inter-arrival jitter |
821// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
822// . .
823// . .
824// . .
825// | inter-arrival jitter |
826// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
827//
828// If present, this RTCP packet must be placed after a receiver report
829// (inside a compound RTCP packet), and MUST have the same value for RC
830// (reception report count) as the receiver report.
831
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000832int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000833RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000834 uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000835 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000836 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000837{
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000838 if (external_report_blocks_.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000839 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000840 // TODO(andresp): Remove external report blocks since they are not
841 // supported.
842 LOG(LS_ERROR) << "Handling of external report blocks not implemented.";
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000843 return 0;
844 }
845
846 // sanity
847 if(pos + 8 >= IP_PACKET_SIZE)
848 {
849 return -2;
850 }
851 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000852 uint8_t RC = 1;
853 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
854 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000855
856 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000857 rtcpbuffer[pos++]=(uint8_t)0;
858 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000859
860 // Add inter-arrival jitter
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000861 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
862 jitterTransmissionTimeOffset);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000863 pos += 4;
864 return 0;
865}
866
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000867int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000868RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000869{
870 // sanity
871 if(pos + 12 >= IP_PACKET_SIZE)
872 {
873 return -2;
874 }
875 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000876 uint8_t FMT = 1;
877 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
878 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000879
880 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000881 rtcpbuffer[pos++]=(uint8_t)0;
882 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000883
884 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000885 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000886 pos += 4;
887
888 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000889 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000890 pos += 4;
891 return 0;
892}
893
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000894int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000895 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000896 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000897 // sanity
898 if(pos + 20 >= IP_PACKET_SIZE) {
899 return -2;
900 }
901 if (!repeat) {
902 _sequenceNumberFIR++; // do not increase if repetition
903 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000904
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000905 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000906 uint8_t FMT = 4;
907 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
908 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000909
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000910 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000911 rtcpbuffer[pos++] = (uint8_t)0;
912 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000913
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000914 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000915 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000916 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000917
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000918 // RFC 5104 4.3.1.2. Semantics
919 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000920 rtcpbuffer[pos++] = (uint8_t)0;
921 rtcpbuffer[pos++] = (uint8_t)0;
922 rtcpbuffer[pos++] = (uint8_t)0;
923 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000924
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000925 // Additional Feedback Control Information (FCI)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000926 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000927 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000928
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000929 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
930 rtcpbuffer[pos++] = (uint8_t)0;
931 rtcpbuffer[pos++] = (uint8_t)0;
932 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000933 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000934}
935
936/*
937 0 1 2 3
938 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
939 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
940 | First | Number | PictureID |
941 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
942*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000943int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000944RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000945{
946 // sanity
947 if(pos + 16 >= IP_PACKET_SIZE)
948 {
949 return -2;
950 }
951 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000952 uint8_t FMT = 2;
953 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
954 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000955
956 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000957 rtcpbuffer[pos++]=(uint8_t)0;
958 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000959
960 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000961 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000962 pos += 4;
963
964 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000965 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000966 pos += 4;
967
968 // Add first, number & picture ID 6 bits
969 // first = 0, 13 - bits
970 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000971 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000972 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, sliField);
niklase@google.com470e71d2011-07-07 08:21:25 +0000973 pos += 4;
974 return 0;
975}
976
977/*
978 0 1 2 3
979 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
980 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
981 | PB |0| Payload Type| Native RPSI bit string |
982 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
983 | defined per codec ... | Padding (0) |
984 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
985*/
986/*
987* Note: not generic made for VP8
988*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000989int32_t
990RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000991 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000992 const uint64_t pictureID,
993 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +0000994{
995 // sanity
996 if(pos + 24 >= IP_PACKET_SIZE)
997 {
998 return -2;
999 }
1000 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001001 uint8_t FMT = 3;
1002 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1003 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001004
1005 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001006 uint32_t bitsRequired = 7;
1007 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001008 while((pictureID>>bitsRequired) > 0)
1009 {
1010 bitsRequired += 7;
1011 bytesRequired++;
1012 }
1013
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001014 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001015 if(bytesRequired > 6)
1016 {
1017 size = 5;
1018 } else if(bytesRequired > 2)
1019 {
1020 size = 4;
1021 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001022 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001023 rtcpbuffer[pos++]=size;
1024
1025 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001026 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001027 pos += 4;
1028
1029 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001030 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001031 pos += 4;
1032
1033 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001034 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001035 if(paddingBytes == 4)
1036 {
1037 paddingBytes = 0;
1038 }
1039 // add padding length in bits
1040 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1041 pos++;
1042
1043 // add payload type
1044 rtcpbuffer[pos] = payloadType;
1045 pos++;
1046
1047 // add picture ID
1048 for(int i = bytesRequired-1; i > 0; i--)
1049 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001050 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001051 pos++;
1052 }
1053 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001054 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001055 pos++;
1056
1057 // add padding
1058 for(int j = 0; j <paddingBytes; j++)
1059 {
1060 rtcpbuffer[pos] = 0;
1061 pos++;
1062 }
1063 return 0;
1064}
1065
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001066int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001067RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001068{
1069 // sanity
1070 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1071 {
1072 return -2;
1073 }
1074 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001075 uint8_t FMT = 15;
1076 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1077 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001078
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001079 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001080 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1081
1082 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001083 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001084 pos += 4;
1085
1086 // Remote SSRC must be 0
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001087 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, 0);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001088 pos += 4;
1089
1090 rtcpbuffer[pos++]='R';
1091 rtcpbuffer[pos++]='E';
1092 rtcpbuffer[pos++]='M';
1093 rtcpbuffer[pos++]='B';
1094
1095 rtcpbuffer[pos++] = _lengthRembSSRC;
1096 // 6 bit Exp
1097 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001098 uint8_t brExp = 0;
1099 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001100 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001101 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001102 {
1103 brExp = i;
1104 break;
1105 }
1106 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001107 const uint32_t brMantissa = (_rembBitrate >> brExp);
1108 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1109 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1110 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001111
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +00001112 for (int i = 0; i < _lengthRembSSRC; i++)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001113 {
1114 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _rembSSRC[i]);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001115 pos += 4;
1116 }
1117 return 0;
1118}
1119
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001120void
1121RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001122{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001123 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001124 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001125}
1126
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001127int32_t RTCPSender::BuildTMMBR(ModuleRtpRtcpImpl* rtp_rtcp_module,
1128 uint8_t* rtcpbuffer,
1129 int& pos) {
1130 if (rtp_rtcp_module == NULL)
1131 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001132 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1133 // If the sender is an owner of the TMMBN -> send TMMBR
1134 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1135
niklase@google.com470e71d2011-07-07 08:21:25 +00001136 // get current bounding set from RTCP receiver
1137 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001138 // store in candidateSet, allocates one extra slot
1139 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001140
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001141 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1142 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1143 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001144 int32_t lengthOfBoundingSet =
1145 rtp_rtcp_module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001146
1147 if(lengthOfBoundingSet > 0)
1148 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001149 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001150 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001151 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1152 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001153 {
1154 // do not send the same tuple
1155 return 0;
1156 }
1157 }
1158 if(!tmmbrOwner)
1159 {
1160 // use received bounding set as candidate set
1161 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001162 candidateSet->SetEntry(lengthOfBoundingSet,
1163 _tmmbr_Send,
1164 _packetOH_Send,
1165 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001166 int numCandidates = lengthOfBoundingSet+ 1;
1167
1168 // find bounding set
1169 TMMBRSet* boundingSet = NULL;
1170 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1171 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1172 {
1173 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1174 }
1175 if(!tmmbrOwner)
1176 {
1177 // did not enter bounding set, no meaning to send this request
1178 return 0;
1179 }
1180 }
1181 }
1182
1183 if(_tmmbr_Send)
1184 {
1185 // sanity
1186 if(pos + 20 >= IP_PACKET_SIZE)
1187 {
1188 return -2;
1189 }
1190 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001191 uint8_t FMT = 3;
1192 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1193 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001194
1195 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001196 rtcpbuffer[pos++]=(uint8_t)0;
1197 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001198
1199 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001200 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001201 pos += 4;
1202
1203 // RFC 5104 4.2.1.2. Semantics
1204
1205 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001206 rtcpbuffer[pos++]=(uint8_t)0;
1207 rtcpbuffer[pos++]=(uint8_t)0;
1208 rtcpbuffer[pos++]=(uint8_t)0;
1209 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001210
1211 // Additional Feedback Control Information (FCI)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001212 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001213 pos += 4;
1214
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001215 uint32_t bitRate = _tmmbr_Send*1000;
1216 uint32_t mmbrExp = 0;
1217 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001218 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001219 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001220 {
1221 mmbrExp = i;
1222 break;
1223 }
1224 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001225 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001226
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001227 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1228 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1229 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1230 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001231 }
1232 return 0;
1233}
1234
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001235int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001236RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001237{
1238 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1239 if(boundingSet == NULL)
1240 {
1241 return -1;
1242 }
1243 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001244 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001245 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001246 LOG(LS_WARNING) << "Failed to build TMMBN.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001247 return -2;
1248 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001249 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001250 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001251 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1252 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001253
1254 //Add length later
1255 int posLength = pos;
1256 pos++;
1257 pos++;
1258
1259 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001260 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001261 pos += 4;
1262
1263 // RFC 5104 4.2.2.2. Semantics
1264
1265 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001266 rtcpbuffer[pos++]=(uint8_t)0;
1267 rtcpbuffer[pos++]=(uint8_t)0;
1268 rtcpbuffer[pos++]=(uint8_t)0;
1269 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001270
1271 // Additional Feedback Control Information (FCI)
1272 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001273 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001274 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001275 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001276 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001277 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001278 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, tmmbrSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001279 pos += 4;
1280
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001281 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1282 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001283 for(int i=0; i<64; i++)
1284 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001285 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001286 {
1287 mmbrExp = i;
1288 break;
1289 }
1290 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001291 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1292 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001293
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001294 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1295 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1296 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1297 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001298 numBoundingSet++;
1299 }
1300 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001301 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1302 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1303 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001304 return 0;
1305}
1306
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001307int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001308RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001309{
1310 // sanity
1311 if(_appData == NULL)
1312 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001313 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001314 return -1;
1315 }
1316 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1317 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001318 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001319 return -2;
1320 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001321 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001322
1323 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001324 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001325
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001326 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1327 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1328 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001329
1330 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001331 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001332 pos += 4;
1333
1334 // Add our application name
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001335 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _appName);
niklase@google.com470e71d2011-07-07 08:21:25 +00001336 pos += 4;
1337
1338 // Add the data
1339 memcpy(rtcpbuffer +pos, _appData,_appLength);
1340 pos += _appLength;
1341 return 0;
1342}
1343
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001344int32_t
1345RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001346 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001347 const int32_t nackSize,
1348 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001349 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001350{
1351 // sanity
1352 if(pos + 16 >= IP_PACKET_SIZE)
1353 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001354 LOG(LS_WARNING) << "Failed to build NACK.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001355 return -2;
1356 }
1357
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001358 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001359 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001360 uint8_t FMT = 1;
1361 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1362 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001363
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001364 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001365 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001366 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001367
1368 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001369 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001370 pos += 4;
1371
1372 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001373 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001374 pos += 4;
1375
edjee@google.com79b02892013-04-04 19:43:34 +00001376 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001377 // Build NACK bitmasks and write them to the RTCP message.
1378 // The nack list should be sorted and not contain duplicates if one
1379 // wants to build the smallest rtcp nack packet.
1380 int numOfNackFields = 0;
1381 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1382 (IP_PACKET_SIZE - pos) / 4);
1383 int i = 0;
1384 while (i < nackSize && numOfNackFields < maxNackFields) {
1385 stringBuilder.PushNACK(nackList[i]);
1386 uint16_t nack = nackList[i++];
1387 uint16_t bitmask = 0;
1388 while (i < nackSize) {
1389 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1390 if (shift >= 0 && shift <= 15) {
1391 stringBuilder.PushNACK(nackList[i]);
1392 bitmask |= (1 << shift);
1393 ++i;
1394 } else {
1395 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001396 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001397 }
1398 // Write the sequence number and the bitmask to the packet.
1399 assert(pos + 4 < IP_PACKET_SIZE);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001400 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001401 pos += 2;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001402 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001403 pos += 2;
1404 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001405 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001406 if (i != nackSize) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001407 LOG(LS_WARNING) << "Nack list to large for one packet.";
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001408 }
1409 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001410 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001411 return 0;
1412}
1413
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001414int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001415RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001416{
1417 // sanity
1418 if(pos + 8 >= IP_PACKET_SIZE)
1419 {
1420 return -2;
1421 }
1422 if(_includeCSRCs)
1423 {
1424 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001425 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1426 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001427
1428 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001429 rtcpbuffer[pos++]=(uint8_t)0;
1430 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001431
1432 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001433 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001434 pos += 4;
1435
1436 // add CSRCs
1437 for(int i = 0; i < _CSRCs; i++)
1438 {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001439 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _CSRC[i]);
niklase@google.com470e71d2011-07-07 08:21:25 +00001440 pos += 4;
1441 }
1442 } else
1443 {
1444 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001445 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1446 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001447
1448 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001449 rtcpbuffer[pos++]=(uint8_t)0;
1450 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001451
1452 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001453 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001454 pos += 4;
1455 }
1456 return 0;
1457}
1458
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001459int32_t RTCPSender::BuildReceiverReferenceTime(uint8_t* buffer,
1460 int& pos,
1461 uint32_t ntp_sec,
1462 uint32_t ntp_frac) {
1463 const int kRrTimeBlockLength = 20;
1464 if (pos + kRrTimeBlockLength >= IP_PACKET_SIZE) {
1465 return -2;
1466 }
1467
1468 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) {
1469 last_xr_rr_.erase(last_xr_rr_.begin());
1470 }
1471 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
1472 RTCPUtility::MidNtp(ntp_sec, ntp_frac),
1473 Clock::NtpToMs(ntp_sec, ntp_frac)));
1474
1475 // Add XR header.
1476 buffer[pos++] = 0x80;
1477 buffer[pos++] = 207;
1478 buffer[pos++] = 0; // XR packet length.
1479 buffer[pos++] = 4; // XR packet length.
1480
1481 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001482 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001483 pos += 4;
1484
1485 // 0 1 2 3
1486 // 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
1487 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1488 // | BT=4 | reserved | block length = 2 |
1489 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1490 // | NTP timestamp, most significant word |
1491 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1492 // | NTP timestamp, least significant word |
1493 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1494
1495 // Add Receiver Reference Time Report block.
1496 buffer[pos++] = 4; // BT.
1497 buffer[pos++] = 0; // Reserved.
1498 buffer[pos++] = 0; // Block length.
1499 buffer[pos++] = 2; // Block length.
1500
1501 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001502 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_sec);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001503 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001504 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001505 pos += 4;
1506
1507 return 0;
1508}
1509
1510int32_t RTCPSender::BuildDlrr(uint8_t* buffer,
1511 int& pos,
1512 const RtcpReceiveTimeInfo& info) {
1513 const int kDlrrBlockLength = 24;
1514 if (pos + kDlrrBlockLength >= IP_PACKET_SIZE) {
1515 return -2;
1516 }
1517
1518 // Add XR header.
1519 buffer[pos++] = 0x80;
1520 buffer[pos++] = 207;
1521 buffer[pos++] = 0; // XR packet length.
1522 buffer[pos++] = 5; // XR packet length.
1523
1524 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001525 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001526 pos += 4;
1527
1528 // 0 1 2 3
1529 // 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
1530 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1531 // | BT=5 | reserved | block length |
1532 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1533 // | SSRC_1 (SSRC of first receiver) | sub-
1534 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1535 // | last RR (LRR) | 1
1536 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1537 // | delay since last RR (DLRR) |
1538 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1539 // | SSRC_2 (SSRC of second receiver) | sub-
1540 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1541 // : ... : 2
1542
1543 // Add DLRR sub block.
1544 buffer[pos++] = 5; // BT.
1545 buffer[pos++] = 0; // Reserved.
1546 buffer[pos++] = 0; // Block length.
1547 buffer[pos++] = 3; // Block length.
1548
1549 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001550 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.sourceSSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001551 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001552 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.lastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001553 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001554 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.delaySinceLastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001555 pos += 4;
1556
1557 return 0;
1558}
1559
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001560int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001561RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001562{
1563 // sanity
1564 if(pos + 44 >= IP_PACKET_SIZE)
1565 {
1566 return -2;
1567 }
1568
1569 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001570 rtcpbuffer[pos++]=(uint8_t)0x80;
1571 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001572
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001573 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001574
1575 // handle length later on
1576 pos++;
1577 pos++;
1578
1579 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001580 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001581 pos += 4;
1582
1583 // Add a VoIP metrics block
1584 rtcpbuffer[pos++]=7;
1585 rtcpbuffer[pos++]=0;
1586 rtcpbuffer[pos++]=0;
1587 rtcpbuffer[pos++]=8;
1588
1589 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001590 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001591 pos += 4;
1592
1593 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1594 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1595 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1596 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1597
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001598 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1599 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1600 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1601 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001602
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001603 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1604 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1605 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1606 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001607
1608 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1609 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1610 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1611 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1612
1613 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1614 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1615 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1616 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1617
1618 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1619 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001620 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1621 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001622
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001623 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1624 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1625 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1626 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001627
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001628 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1629 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001630 return 0;
1631}
1632
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001633int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
1634 uint32_t packetTypeFlags,
1635 int32_t nackSize,
1636 const uint16_t* nackList,
1637 bool repeat,
1638 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001639 {
1640 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1641 if(_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001642 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001643 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001644 return -1;
1645 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001646 }
1647 uint8_t rtcp_buffer[IP_PACKET_SIZE];
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001648 int rtcp_length = PrepareRTCP(feedback_state,
1649 packetTypeFlags,
1650 nackSize,
1651 nackList,
1652 repeat,
1653 pictureID,
1654 rtcp_buffer,
1655 IP_PACKET_SIZE);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001656 if (rtcp_length < 0) {
1657 return -1;
1658 }
1659 // Sanity don't send empty packets.
1660 if (rtcp_length == 0)
1661 {
1662 return -1;
1663 }
1664 return SendToNetwork(rtcp_buffer, static_cast<uint16_t>(rtcp_length));
1665}
1666
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001667int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
1668 uint32_t packetTypeFlags,
1669 int32_t nackSize,
1670 const uint16_t* nackList,
1671 bool repeat,
1672 uint64_t pictureID,
1673 uint8_t* rtcp_buffer,
1674 int buffer_size) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001675 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1676 // Collect the received information.
1677 uint32_t NTPsec = 0;
1678 uint32_t NTPfrac = 0;
1679 uint32_t jitterTransmissionOffset = 0;
1680 int position = 0;
1681
1682 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1683
1684 if(_TMMBR ) // Attach TMMBR to send and receive reports.
1685 {
1686 rtcpPacketTypeFlags |= kRtcpTmmbr;
1687 }
1688 if(_appSend)
1689 {
1690 rtcpPacketTypeFlags |= kRtcpApp;
1691 _appSend = false;
1692 }
1693 if(_REMB && _sendREMB)
1694 {
1695 // Always attach REMB to SR if that is configured. Note that REMB is
1696 // only sent on one of the RTP modules in the REMB group.
1697 rtcpPacketTypeFlags |= kRtcpRemb;
1698 }
1699 if(_xrSendVoIPMetric)
1700 {
1701 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1702 _xrSendVoIPMetric = false;
1703 }
1704 if(_sendTMMBN) // Set when having received a TMMBR.
1705 {
1706 rtcpPacketTypeFlags |= kRtcpTmmbn;
1707 _sendTMMBN = false;
1708 }
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001709 if (rtcpPacketTypeFlags & kRtcpReport)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001710 {
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001711 if (xrSendReceiverReferenceTimeEnabled_ && !_sending)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001712 {
1713 rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
1714 }
1715 if (feedback_state.has_last_xr_rr)
1716 {
1717 rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
1718 }
1719 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001720 if(_method == kRtcpCompound)
1721 {
1722 if(_sending)
1723 {
1724 rtcpPacketTypeFlags |= kRtcpSr;
1725 } else
1726 {
1727 rtcpPacketTypeFlags |= kRtcpRr;
1728 }
1729 } else if(_method == kRtcpNonCompound)
1730 {
1731 if(rtcpPacketTypeFlags & kRtcpReport)
1732 {
1733 if(_sending)
1734 {
1735 rtcpPacketTypeFlags |= kRtcpSr;
1736 } else
1737 {
1738 rtcpPacketTypeFlags |= kRtcpRr;
1739 }
1740 }
1741 }
1742 if( rtcpPacketTypeFlags & kRtcpRr ||
1743 rtcpPacketTypeFlags & kRtcpSr)
1744 {
1745 // generate next time to send a RTCP report
1746 // seeded from RTP constructor
1747 int32_t random = rand() % 1000;
1748 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1749
1750 if(_audio)
1751 {
1752 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1753 (RTCP_INTERVAL_AUDIO_MS*random/1000);
1754 }else
1755 {
1756 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1757 if(_sending)
1758 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001759 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1760 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1761 if (send_bitrate_kbit != 0)
1762 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001763 }
1764 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1765 {
1766 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1767 }
1768 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1769 }
1770 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1771 }
1772
1773 // If the data does not fit in the packet we fill it as much as possible.
1774 int32_t buildVal = 0;
1775
1776 // We need to send our NTP even if we haven't received any reports.
1777 _clock->CurrentNtp(NTPsec, NTPfrac);
1778 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1779 StatisticianMap statisticians =
1780 receive_statistics_->GetActiveStatisticians();
1781 if (!statisticians.empty()) {
1782 StatisticianMap::const_iterator it;
1783 int i;
1784 for (it = statisticians.begin(), i = 0; it != statisticians.end();
1785 ++it, ++i) {
1786 RTCPReportBlock report_block;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001787 if (PrepareReport(
1788 feedback_state, it->second, &report_block, &NTPsec, &NTPfrac))
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001789 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1790 }
1791 if (_IJ && !statisticians.empty()) {
1792 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1793 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001794 }
1795 }
1796
1797 if(rtcpPacketTypeFlags & kRtcpSr)
1798 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001799 buildVal = BuildSR(feedback_state, rtcp_buffer, position, NTPsec, NTPfrac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001800 if (buildVal == -1) {
1801 return -1;
1802 } else if (buildVal == -2) {
1803 return position;
1804 }
1805 buildVal = BuildSDEC(rtcp_buffer, position);
1806 if (buildVal == -1) {
1807 return -1;
1808 } else if (buildVal == -2) {
1809 return position;
1810 }
1811 }else if(rtcpPacketTypeFlags & kRtcpRr)
1812 {
1813 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1814 if (buildVal == -1) {
1815 return -1;
1816 } else if (buildVal == -2) {
1817 return position;
1818 }
1819 // only of set
1820 if(_CNAME[0] != 0)
1821 {
1822 buildVal = BuildSDEC(rtcp_buffer, position);
1823 if (buildVal == -1) {
1824 return -1;
1825 }
1826 }
1827 }
1828 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1829 {
1830 // If present, this RTCP packet must be placed after a
1831 // receiver report.
1832 buildVal = BuildExtendedJitterReport(rtcp_buffer,
1833 position,
1834 jitterTransmissionOffset);
1835 if (buildVal == -1) {
1836 return -1;
1837 } else if (buildVal == -2) {
1838 return position;
1839 }
1840 }
1841 if(rtcpPacketTypeFlags & kRtcpPli)
1842 {
1843 buildVal = BuildPLI(rtcp_buffer, position);
1844 if (buildVal == -1) {
1845 return -1;
1846 } else if (buildVal == -2) {
1847 return position;
1848 }
1849 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001850 ++packet_type_counter_.pli_packets;
1851 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC,
1852 packet_type_counter_.pli_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001853 }
1854 if(rtcpPacketTypeFlags & kRtcpFir)
1855 {
1856 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1857 if (buildVal == -1) {
1858 return -1;
1859 } else if (buildVal == -2) {
1860 return position;
1861 }
1862 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001863 ++packet_type_counter_.fir_packets;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001864 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001865 packet_type_counter_.fir_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001866 }
1867 if(rtcpPacketTypeFlags & kRtcpSli)
1868 {
1869 buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1870 if (buildVal == -1) {
1871 return -1;
1872 } else if (buildVal == -2) {
1873 return position;
1874 }
1875 }
1876 if(rtcpPacketTypeFlags & kRtcpRpsi)
1877 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001878 const int8_t payloadType = feedback_state.send_payload_type;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001879 if (payloadType == -1) {
1880 return -1;
1881 }
1882 buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1883 (uint8_t)payloadType);
1884 if (buildVal == -1) {
1885 return -1;
1886 } else if (buildVal == -2) {
1887 return position;
1888 }
1889 }
1890 if(rtcpPacketTypeFlags & kRtcpRemb)
1891 {
1892 buildVal = BuildREMB(rtcp_buffer, position);
1893 if (buildVal == -1) {
1894 return -1;
1895 } else if (buildVal == -2) {
1896 return position;
1897 }
1898 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1899 }
1900 if(rtcpPacketTypeFlags & kRtcpBye)
1901 {
1902 buildVal = BuildBYE(rtcp_buffer, position);
1903 if (buildVal == -1) {
1904 return -1;
1905 } else if (buildVal == -2) {
1906 return position;
1907 }
1908 }
1909 if(rtcpPacketTypeFlags & kRtcpApp)
1910 {
1911 buildVal = BuildAPP(rtcp_buffer, position);
1912 if (buildVal == -1) {
1913 return -1;
1914 } else if (buildVal == -2) {
1915 return position;
1916 }
1917 }
1918 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1919 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001920 buildVal = BuildTMMBR(feedback_state.module, rtcp_buffer, position);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001921 if (buildVal == -1) {
1922 return -1;
1923 } else if (buildVal == -2) {
1924 return position;
1925 }
1926 }
1927 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1928 {
1929 buildVal = BuildTMMBN(rtcp_buffer, position);
1930 if (buildVal == -1) {
1931 return -1;
1932 } else if (buildVal == -2) {
1933 return position;
1934 }
1935 }
1936 if(rtcpPacketTypeFlags & kRtcpNack)
1937 {
1938 std::string nackString;
1939 buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
1940 &nackString);
1941 if (buildVal == -1) {
1942 return -1;
1943 } else if (buildVal == -2) {
1944 return position;
1945 }
1946 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
1947 "nacks", TRACE_STR_COPY(nackString.c_str()));
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001948 ++packet_type_counter_.nack_packets;
1949 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC,
1950 packet_type_counter_.nack_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001951 }
1952 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1953 {
1954 buildVal = BuildVoIPMetric(rtcp_buffer, position);
1955 if (buildVal == -1) {
1956 return -1;
1957 } else if (buildVal == -2) {
1958 return position;
1959 }
1960 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001961 if (rtcpPacketTypeFlags & kRtcpXrReceiverReferenceTime)
1962 {
1963 buildVal = BuildReceiverReferenceTime(rtcp_buffer,
1964 position,
1965 NTPsec,
1966 NTPfrac);
1967 if (buildVal == -1) {
1968 return -1;
1969 } else if (buildVal == -2) {
1970 return position;
1971 }
1972 }
1973 if (rtcpPacketTypeFlags & kRtcpXrDlrrReportBlock)
1974 {
1975 buildVal = BuildDlrr(rtcp_buffer, position, feedback_state.last_xr_rr);
1976 if (buildVal == -1) {
1977 return -1;
1978 } else if (buildVal == -2) {
1979 return position;
1980 }
1981 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001982 return position;
1983}
1984
1985bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
1986 return Status() == kRtcpCompound ||
1987 (rtcp_packet_type & kRtcpReport) ||
1988 (rtcp_packet_type & kRtcpSr) ||
1989 (rtcp_packet_type & kRtcpRr);
1990}
1991
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001992bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
1993 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001994 RTCPReportBlock* report_block,
1995 uint32_t* ntp_secs, uint32_t* ntp_frac) {
1996 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001997 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001998 if (!statistician->GetStatistics(&stats, true))
1999 return false;
2000 report_block->fractionLost = stats.fraction_lost;
2001 report_block->cumulativeLost = stats.cumulative_lost;
2002 report_block->extendedHighSeqNum =
2003 stats.extended_max_sequence_number;
2004 report_block->jitter = stats.jitter;
2005
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002006 // get our NTP as late as possible to avoid a race
2007 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
2008
2009 // Delay since last received report
2010 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002011 if ((feedback_state.last_rr_ntp_secs != 0) ||
2012 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002013 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
2014 uint32_t now=*ntp_secs&0x0000FFFF;
2015 now <<=16;
2016 now += (*ntp_frac&0xffff0000)>>16;
2017
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002018 uint32_t receiveTime = feedback_state.last_rr_ntp_secs&0x0000FFFF;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002019 receiveTime <<=16;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002020 receiveTime += (feedback_state.last_rr_ntp_frac&0xffff0000)>>16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002021
2022 delaySinceLastReceivedSR = now-receiveTime;
2023 }
2024 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002025 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002026 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00002027}
2028
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002029int32_t
2030RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
2031 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002032{
2033 CriticalSectionScoped lock(_criticalSectionTransport);
2034 if(_cbTransport)
2035 {
2036 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
2037 {
2038 return 0;
2039 }
2040 }
2041 return -1;
2042}
2043
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002044int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002045RTCPSender::SetCSRCStatus(const bool include)
2046{
pbos@webrtc.org180e5162014-07-11 15:36:26 +00002047 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +00002048 _includeCSRCs = include;
2049 return 0;
2050}
2051
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002052int32_t
2053RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
2054 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00002055{
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002056 assert(arrLength <= kRtpCsrcSize);
niklase@google.com470e71d2011-07-07 08:21:25 +00002057 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2058
2059 for(int i = 0; i < arrLength;i++)
2060 {
2061 _CSRC[i] = arrOfCSRC[i];
2062 }
2063 _CSRCs = arrLength;
2064 return 0;
2065}
2066
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002067int32_t
2068RTCPSender::SetApplicationSpecificData(const uint8_t subType,
2069 const uint32_t name,
2070 const uint8_t* data,
2071 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002072{
2073 if(length %4 != 0)
2074 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002075 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
niklase@google.com470e71d2011-07-07 08:21:25 +00002076 return -1;
2077 }
2078 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2079
2080 if(_appData)
2081 {
2082 delete [] _appData;
2083 }
2084
2085 _appSend = true;
2086 _appSubType = subType;
2087 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002088 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002089 _appLength = length;
2090 memcpy(_appData, data, length);
2091 return 0;
2092}
2093
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002094int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002095RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2096{
2097 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2098 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2099
2100 _xrSendVoIPMetric = true;
2101 return 0;
2102}
2103
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002104void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
2105 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2106 xrSendReceiverReferenceTimeEnabled_ = enable;
2107}
2108
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00002109bool RTCPSender::RtcpXrReceiverReferenceTime() const {
2110 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2111 return xrSendReceiverReferenceTimeEnabled_;
2112}
2113
niklase@google.com470e71d2011-07-07 08:21:25 +00002114// called under critsect _criticalSectionRTCPSender
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002115int32_t RTCPSender::WriteAllReportBlocksToBuffer(
2116 uint8_t* rtcpbuffer,
2117 int pos,
2118 uint8_t& numberOfReportBlocks,
2119 const uint32_t NTPsec,
2120 const uint32_t NTPfrac) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002121 numberOfReportBlocks = external_report_blocks_.size();
2122 numberOfReportBlocks += internal_report_blocks_.size();
2123 if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002124 LOG(LS_WARNING) << "Can't fit all report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002125 return -1;
2126 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002127 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2128 while (!internal_report_blocks_.empty()) {
2129 delete internal_report_blocks_.begin()->second;
2130 internal_report_blocks_.erase(internal_report_blocks_.begin());
2131 }
2132 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2133 return pos;
2134}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002135
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002136int32_t RTCPSender::WriteReportBlocksToBuffer(
2137 uint8_t* rtcpbuffer,
2138 int32_t position,
2139 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2140 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2141 report_blocks.begin();
2142 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002143 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002144 RTCPReportBlock* reportBlock = it->second;
2145 if (reportBlock) {
2146 // Remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002147 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position, remoteSSRC);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002148 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002149
2150 // fraction lost
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002151 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002152
2153 // cumulative loss
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002154 RtpUtility::AssignUWord24ToBuffer(rtcpbuffer + position,
2155 reportBlock->cumulativeLost);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002156 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002157
2158 // extended highest seq_no, contain the highest sequence number received
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002159 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2160 reportBlock->extendedHighSeqNum);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002161 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002162
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002163 // Jitter
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002164 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2165 reportBlock->jitter);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002166 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002167
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002168 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2169 reportBlock->lastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002170 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002171
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002172 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2173 reportBlock->delaySinceLastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002174 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002175 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002176 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002177 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00002178}
2179
2180// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002181int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002182RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002183 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002184{
2185 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2186
2187 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2188 {
2189 _sendTMMBN = true;
2190 return 0;
2191 }
2192 return -1;
2193}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002194} // namespace webrtc