blob: c3bc8f5e468f963b141496e020721bb4d404571e [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
andresp@webrtc.org523f9372013-04-11 11:30:39 +000013#include <algorithm> // min
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000014#include <cassert> // assert
15#include <cstdlib> // rand
16#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000017
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000018#include "webrtc/common_types.h"
19#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
20#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
21#include "webrtc/system_wrappers/interface/trace.h"
22#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000023
niklase@google.com470e71d2011-07-07 08:21:25 +000024namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000025
26using RTCPUtility::RTCPCnameInformation;
27
edjee@google.com79b02892013-04-04 19:43:34 +000028NACKStringBuilder::NACKStringBuilder() :
29 _stream(""), _count(0), _consecutive(false)
30{
31 // Empty.
32}
33
pbos@webrtc.org2f446732013-04-08 11:08:41 +000034void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000035{
36 if (_count == 0)
37 {
38 _stream << nack;
39 } else if (nack == _prevNack + 1)
40 {
41 _consecutive = true;
42 } else
43 {
44 if (_consecutive)
45 {
46 _stream << "-" << _prevNack;
47 _consecutive = false;
48 }
49 _stream << "," << nack;
50 }
51 _count++;
52 _prevNack = nack;
53}
54
55std::string NACKStringBuilder::GetResult()
56{
57 if (_consecutive)
58 {
59 _stream << "-" << _prevNack;
60 _consecutive = false;
61 }
62 return _stream.str();
63}
64
pbos@webrtc.org2f446732013-04-08 11:08:41 +000065RTCPSender::RTCPSender(const int32_t id,
niklase@google.com470e71d2011-07-07 08:21:25 +000066 const bool audio,
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000067 Clock* clock,
stefan@webrtc.org717d1472013-07-10 13:39:27 +000068 ModuleRtpRtcpImpl* owner,
69 ReceiveStatistics* receive_statistics) :
niklase@google.com470e71d2011-07-07 08:21:25 +000070 _id(id),
71 _audio(audio),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000072 _clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000073 _method(kRtcpOff),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000074 _rtpRtcp(*owner),
henrike@webrtc.org65573f22011-12-13 19:17:27 +000075 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000076 _cbTransport(NULL),
77
henrike@webrtc.org65573f22011-12-13 19:17:27 +000078 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000079 _usingNack(false),
80 _sending(false),
81 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000082 _REMB(false),
83 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000084 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +000085 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000086 _nextTimeToSendRTCP(0),
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000087 start_timestamp_(0),
88 last_rtp_timestamp_(0),
89 last_frame_capture_time_ms_(-1),
niklase@google.com470e71d2011-07-07 08:21:25 +000090 _SSRC(0),
91 _remoteSSRC(0),
92 _CNAME(),
stefan@webrtc.org717d1472013-07-10 13:39:27 +000093 receive_statistics_(receive_statistics),
94 internal_report_blocks_(),
95 external_report_blocks_(),
niklase@google.com470e71d2011-07-07 08:21:25 +000096 _csrcCNAMEs(),
97
stefan@webrtc.org7da34592013-04-09 14:56:29 +000098 _cameraDelayMS(0),
99
niklase@google.com470e71d2011-07-07 08:21:25 +0000100 _lastSendReport(),
101 _lastRTCPTime(),
102
103 _CSRCs(0),
104 _CSRC(),
105 _includeCSRCs(true),
106
107 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000108
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000109 _lengthRembSSRC(0),
110 _sizeRembSSRC(0),
111 _rembSSRC(NULL),
112 _rembBitrate(0),
113
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000114 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000115 _tmmbr_Send(0),
116 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000117
118 _appSend(false),
119 _appSubType(0),
120 _appName(),
121 _appData(NULL),
122 _appLength(0),
123 _xrSendVoIPMetric(false),
edjee@google.com79b02892013-04-04 19:43:34 +0000124 _xrVoIPMetric(),
125 _nackCount(0),
126 _pliCount(0),
127 _fullIntraRequestCount(0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000128{
129 memset(_CNAME, 0, sizeof(_CNAME));
130 memset(_lastSendReport, 0, sizeof(_lastSendReport));
131 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
132
133 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
134}
135
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000136RTCPSender::~RTCPSender() {
137 delete [] _rembSSRC;
138 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000139
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000140 while (!internal_report_blocks_.empty()) {
141 delete internal_report_blocks_.begin()->second;
142 internal_report_blocks_.erase(internal_report_blocks_.begin());
143 }
144 while (!external_report_blocks_.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000145 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000146 external_report_blocks_.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000147 delete it->second;
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000148 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000149 }
150 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000151 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000152 _csrcCNAMEs.begin();
153 delete it->second;
154 _csrcCNAMEs.erase(it);
155 }
156 delete _criticalSectionTransport;
157 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000158
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000159 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000160}
161
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000162int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000163RTCPSender::Init()
164{
165 CriticalSectionScoped lock(_criticalSectionRTCPSender);
166
167 _method = kRtcpOff;
168 _cbTransport = NULL;
169 _usingNack = false;
170 _sending = false;
171 _sendTMMBN = false;
172 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000173 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000174 _REMB = false;
175 _sendREMB = false;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000176 last_rtp_timestamp_ = 0;
177 last_frame_capture_time_ms_ = -1;
178 start_timestamp_ = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000179 _SSRC = 0;
180 _remoteSSRC = 0;
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000181 _cameraDelayMS = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000182 _sequenceNumberFIR = 0;
183 _tmmbr_Send = 0;
184 _packetOH_Send = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000185 _nextTimeToSendRTCP = 0;
186 _CSRCs = 0;
187 _appSend = false;
188 _appSubType = 0;
189
190 if(_appData)
191 {
192 delete [] _appData;
193 _appData = NULL;
194 }
195 _appLength = 0;
196
197 _xrSendVoIPMetric = false;
198
199 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
200 memset(_CNAME, 0, sizeof(_CNAME));
201 memset(_lastSendReport, 0, sizeof(_lastSendReport));
202 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
edjee@google.com79b02892013-04-04 19:43:34 +0000203
204 _nackCount = 0;
205 _pliCount = 0;
206 _fullIntraRequestCount = 0;
207
niklase@google.com470e71d2011-07-07 08:21:25 +0000208 return 0;
209}
210
211void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000212RTCPSender::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +0000213{
214 _id = id;
215}
216
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000217int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000218RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
219{
220 CriticalSectionScoped lock(_criticalSectionTransport);
221 _cbTransport = outgoingTransport;
222 return 0;
223}
224
225RTCPMethod
226RTCPSender::Status() const
227{
228 CriticalSectionScoped lock(_criticalSectionRTCPSender);
229 return _method;
230}
231
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000232int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000233RTCPSender::SetRTCPStatus(const RTCPMethod method)
234{
235 CriticalSectionScoped lock(_criticalSectionRTCPSender);
236 if(method != kRtcpOff)
237 {
238 if(_audio)
239 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000240 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000241 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000242 } else
243 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000244 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000245 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000246 }
247 }
248 _method = method;
249 return 0;
250}
251
252bool
253RTCPSender::Sending() const
254{
255 CriticalSectionScoped lock(_criticalSectionRTCPSender);
256 return _sending;
257}
258
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000259int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000260RTCPSender::SetSendingStatus(const bool sending)
261{
262 bool sendRTCPBye = false;
263 {
264 CriticalSectionScoped lock(_criticalSectionRTCPSender);
265
266 if(_method != kRtcpOff)
267 {
268 if(sending == false && _sending == true)
269 {
270 // Trigger RTCP bye
271 sendRTCPBye = true;
272 }
273 }
274 _sending = sending;
275 }
276 if(sendRTCPBye)
277 {
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000278 return SendRTCP(kRtcpBye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000279 }
280 return 0;
281}
282
283bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000284RTCPSender::REMB() const
285{
286 CriticalSectionScoped lock(_criticalSectionRTCPSender);
287 return _REMB;
288}
289
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000290int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000291RTCPSender::SetREMBStatus(const bool enable)
292{
293 CriticalSectionScoped lock(_criticalSectionRTCPSender);
294 _REMB = enable;
295 return 0;
296}
297
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000298int32_t
299RTCPSender::SetREMBData(const uint32_t bitrate,
300 const uint8_t numberOfSSRC,
301 const uint32_t* SSRC)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000302{
303 CriticalSectionScoped lock(_criticalSectionRTCPSender);
304 _rembBitrate = bitrate;
305
306 if(_sizeRembSSRC < numberOfSSRC)
307 {
308 delete [] _rembSSRC;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000309 _rembSSRC = new uint32_t[numberOfSSRC];
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000310 _sizeRembSSRC = numberOfSSRC;
311 }
312
313 _lengthRembSSRC = numberOfSSRC;
314 for (int i = 0; i < numberOfSSRC; i++)
315 {
316 _rembSSRC[i] = SSRC[i];
317 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000318 _sendREMB = true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000319 return 0;
320}
321
322bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000323RTCPSender::TMMBR() const
324{
325 CriticalSectionScoped lock(_criticalSectionRTCPSender);
326 return _TMMBR;
327}
328
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000329int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000330RTCPSender::SetTMMBRStatus(const bool enable)
331{
332 CriticalSectionScoped lock(_criticalSectionRTCPSender);
333 _TMMBR = enable;
334 return 0;
335}
336
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000337bool
338RTCPSender::IJ() const
339{
340 CriticalSectionScoped lock(_criticalSectionRTCPSender);
341 return _IJ;
342}
343
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000344int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000345RTCPSender::SetIJStatus(const bool enable)
346{
347 CriticalSectionScoped lock(_criticalSectionRTCPSender);
348 _IJ = enable;
349 return 0;
350}
351
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000352void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
353 start_timestamp_ = start_timestamp;
354}
355
356void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
357 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000358 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000359 last_rtp_timestamp_ = rtp_timestamp;
360 if (capture_time_ms < 0) {
361 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000362 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000363 } else {
364 last_frame_capture_time_ms_ = capture_time_ms;
365 }
366}
367
niklase@google.com470e71d2011-07-07 08:21:25 +0000368void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000369RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000370{
371 CriticalSectionScoped lock(_criticalSectionRTCPSender);
372
373 if(_SSRC != 0)
374 {
375 // not first SetSSRC, probably due to a collision
376 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000377 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000378 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000379 }
380 _SSRC = ssrc;
381}
382
stefan@webrtc.org66b2e5c2013-07-05 14:30:48 +0000383void RTCPSender::SetRemoteSSRC(uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000384{
385 CriticalSectionScoped lock(_criticalSectionRTCPSender);
386 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000387}
388
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000389int32_t
390RTCPSender::SetCameraDelay(const int32_t delayMS)
391{
392 CriticalSectionScoped lock(_criticalSectionRTCPSender);
393 if(delayMS > 1000 || delayMS < -1000)
394 {
395 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
396 return -1;
397 }
398 _cameraDelayMS = delayMS;
399 return 0;
400}
401
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000402int32_t RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000403 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000404 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000405 cName[RTCP_CNAME_SIZE - 1] = 0;
406 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000407 return 0;
408}
409
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000410int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000411 if (!cName)
412 return -1;
413
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000414 CriticalSectionScoped lock(_criticalSectionRTCPSender);
415 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
416 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
417 return 0;
418}
419
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000420int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
421 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000422 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000423 CriticalSectionScoped lock(_criticalSectionRTCPSender);
424 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
425 return -1;
426 }
427 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000428 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
429 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000430 _csrcCNAMEs[SSRC] = ptr;
431 return 0;
432}
433
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000434int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000435 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000436 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000437 _csrcCNAMEs.find(SSRC);
438
439 if (it == _csrcCNAMEs.end()) {
440 return -1;
441 }
442 delete it->second;
443 _csrcCNAMEs.erase(it);
444 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000445}
446
447bool
448RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
449{
450/*
451 For audio we use a fix 5 sec interval
452
453 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
454 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
455
456
457From RFC 3550
458
459 MAX RTCP BW is 5% if the session BW
460 A send report is approximately 65 bytes inc CNAME
461 A report report is approximately 28 bytes
462
463 The RECOMMENDED value for the reduced minimum in seconds is 360
464 divided by the session bandwidth in kilobits/second. This minimum
465 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
466
467 If the participant has not yet sent an RTCP packet (the variable
468 initial is true), the constant Tmin is set to 2.5 seconds, else it
469 is set to 5 seconds.
470
471 The interval between RTCP packets is varied randomly over the
472 range [0.5,1.5] times the calculated interval to avoid unintended
473 synchronization of all participants
474
475 if we send
476 If the participant is a sender (we_sent true), the constant C is
477 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
478 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
479 number of senders.
480
481 if we receive only
482 If we_sent is not true, the constant C is set
483 to the average RTCP packet size divided by 75% of the RTCP
484 bandwidth. The constant n is set to the number of receivers
485 (members - senders). If the number of senders is greater than
486 25%, senders and receivers are treated together.
487
488 reconsideration NOT required for peer-to-peer
489 "timer reconsideration" is
490 employed. This algorithm implements a simple back-off mechanism
491 which causes users to hold back RTCP packet transmission if the
492 group sizes are increasing.
493
494 n = number of members
495 C = avg_size/(rtcpBW/4)
496
497 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
498
499 4. The calculated interval T is set to a number uniformly distributed
500 between 0.5 and 1.5 times the deterministic calculated interval.
501
502 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
503 for the fact that the timer reconsideration algorithm converges to
504 a value of the RTCP bandwidth below the intended average
505*/
506
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000507 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000508
509 CriticalSectionScoped lock(_criticalSectionRTCPSender);
510
niklase@google.com470e71d2011-07-07 08:21:25 +0000511 if(_method == kRtcpOff)
512 {
513 return false;
514 }
515
niklase@google.com470e71d2011-07-07 08:21:25 +0000516 if(!_audio && sendKeyframeBeforeRTP)
517 {
518 // for video key-frames we want to send the RTCP before the large key-frame
519 // if we have a 100 ms margin
520 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
521 }
522
523 if(now > _nextTimeToSendRTCP)
524 {
525 return true;
526
527 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
528 {
529 // wrap
530 return true;
531 }
532 return false;
533}
534
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000535uint32_t
536RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000537{
538 CriticalSectionScoped lock(_criticalSectionRTCPSender);
539
540 lastRTCPTime = _lastRTCPTime[0];
541 return _lastSendReport[0];
542}
543
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000544uint32_t
545RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000546{
547 CriticalSectionScoped lock(_criticalSectionRTCPSender);
548
549 // This is only saved when we are the sender
550 if((_lastSendReport[0] == 0) || (sendReport == 0))
551 {
552 return 0; // will be ignored
553 } else
554 {
555 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
556 {
557 if( _lastSendReport[i] == sendReport)
558 {
559 return _lastRTCPTime[i];
560 }
561 }
562 }
563 return 0;
564}
565
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000566int32_t RTCPSender::AddExternalReportBlock(
567 uint32_t SSRC,
568 const RTCPReportBlock* reportBlock) {
569 CriticalSectionScoped lock(_criticalSectionRTCPSender);
570 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
571}
572
573int32_t RTCPSender::AddReportBlock(
574 uint32_t SSRC,
575 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
576 const RTCPReportBlock* reportBlock) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000577 if (reportBlock == NULL) {
578 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
579 "%s invalid argument", __FUNCTION__);
580 return -1;
581 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000582
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000583 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000584 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
585 "%s invalid argument", __FUNCTION__);
586 return -1;
587 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000588 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000589 report_blocks->find(SSRC);
590 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000591 delete it->second;
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000592 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000593 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000594 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
595 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000596 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000597 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000598}
599
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000600int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000601 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000602
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000603 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000604 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000605
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000606 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000607 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000608 }
609 delete it->second;
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000610 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000611 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000612}
613
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000614int32_t
615RTCPSender::BuildSR(uint8_t* rtcpbuffer,
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000616 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000617 const uint32_t NTPsec,
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000618 const uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000619{
620 // sanity
621 if(pos + 52 >= IP_PACKET_SIZE)
622 {
623 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
624 return -2;
625 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000626 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000627
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000628 uint32_t posNumberOfReportBlocks = pos;
629 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000630
631 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000632 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000633
634 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
635 {
636 // shift old
637 _lastSendReport[i+1] = _lastSendReport[i];
638 _lastRTCPTime[i+1] =_lastRTCPTime[i];
639 }
640
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000641 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000642 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000643
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000644 uint32_t freqHz = 90000; // For video
645 if(_audio) {
646 freqHz = _rtpRtcp.CurrentSendFrequencyHz();
niklase@google.com470e71d2011-07-07 08:21:25 +0000647 }
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000648
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000649 // The timestamp of this RTCP packet should be estimated as the timestamp of
650 // the frame being captured at this moment. We are calculating that
651 // timestamp as the last frame's timestamp + the time since the last frame
652 // was captured.
653 {
654 // Needs protection since this method is called on the process thread.
655 CriticalSectionScoped lock(_criticalSectionRTCPSender);
656 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
657 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
658 (freqHz / 1000);
659 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000660
661 // Add sender data
662 // Save for our length field
663 pos++;
664 pos++;
665
666 // Add our own SSRC
667 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
668 pos += 4;
669 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000670 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000671 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000672 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000673 pos += 4;
674 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
675 pos += 4;
676
677 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000678 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000679 pos += 4;
680
681 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000682 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000683 pos += 4;
684
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000685 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000686 int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
687 numberOfReportBlocks,
688 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000689 if(retVal < 0)
690 {
691 //
692 return retVal ;
693 }
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000694 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000695 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
696
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000697 uint16_t len = uint16_t((pos/4) -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000698 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
699 return 0;
700}
701
702
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000703int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer,
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000704 int& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000705 size_t lengthCname = strlen(_CNAME);
706 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000707
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000708 // sanity
709 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
710 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
711 "%s invalid argument", __FUNCTION__);
712 return -2;
713 }
714 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000715
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000716 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000717 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
718 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000719
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000720 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000721 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000722 pos++;
723 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000724
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000725 // Add our own SSRC
726 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
727 pos += 4;
728
729 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000730 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000731
732 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000733 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000734
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000735 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000736
737 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
738 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000739 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000740
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000741 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000742 // We must have a zero field even if we have an even multiple of 4 bytes
743 if ((pos % 4) == 0) {
744 padding++;
745 rtcpbuffer[pos++]=0;
746 }
747 while ((pos % 4) != 0) {
748 padding++;
749 rtcpbuffer[pos++]=0;
750 }
751 SDESLength += padding;
752
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000753 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000754 _csrcCNAMEs.begin();
755
756 for(; it != _csrcCNAMEs.end(); it++) {
757 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000758 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000759
760 // Add SSRC
761 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000762 pos += 4;
763
764 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000765 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000766
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000767 size_t length = strlen(cname->name);
768 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000769
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000770 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000771 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000772
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000773 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000774
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000775 pos += length;
776 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000777 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000778
779 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000780 if((pos % 4) == 0){
781 padding++;
782 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000783 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000784 while((pos % 4) != 0){
785 padding++;
786 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000787 }
788 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000789 }
790 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000791 uint16_t buffer_length = (SDESLength / 4) - 1;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000792 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
793 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000794 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000795}
796
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000797int32_t
798RTCPSender::BuildRR(uint8_t* rtcpbuffer,
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000799 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000800 const uint32_t NTPsec,
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000801 const uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000802{
803 // sanity one block
804 if(pos + 32 >= IP_PACKET_SIZE)
805 {
806 return -2;
807 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000808 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000809
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000810 rtcpbuffer[pos++]=(uint8_t)0x80;
811 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000812
813 // Save for our length field
814 pos++;
815 pos++;
816
817 // Add our own SSRC
818 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
819 pos += 4;
820
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000821 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000822 int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
823 numberOfReportBlocks,
824 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000825 if(retVal < 0)
826 {
827 return retVal;
828 }
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000829 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000830 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
831
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000832 uint16_t len = uint16_t((pos)/4 -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000833 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
834 return 0;
835}
836
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000837// From RFC 5450: Transmission Time Offsets in RTP Streams.
838// 0 1 2 3
839// 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
840// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
841// hdr |V=2|P| RC | PT=IJ=195 | length |
842// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
843// | inter-arrival jitter |
844// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
845// . .
846// . .
847// . .
848// | inter-arrival jitter |
849// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
850//
851// If present, this RTCP packet must be placed after a receiver report
852// (inside a compound RTCP packet), and MUST have the same value for RC
853// (reception report count) as the receiver report.
854
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000855int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000856RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000857 uint8_t* rtcpbuffer,
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000858 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000859 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000860{
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000861 if (external_report_blocks_.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000862 {
863 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
864 return 0;
865 }
866
867 // sanity
868 if(pos + 8 >= IP_PACKET_SIZE)
869 {
870 return -2;
871 }
872 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000873 uint8_t RC = 1;
874 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
875 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000876
877 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000878 rtcpbuffer[pos++]=(uint8_t)0;
879 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000880
881 // Add inter-arrival jitter
882 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
883 jitterTransmissionTimeOffset);
884 pos += 4;
885 return 0;
886}
887
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000888int32_t
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000889RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000890{
891 // sanity
892 if(pos + 12 >= IP_PACKET_SIZE)
893 {
894 return -2;
895 }
896 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000897 uint8_t FMT = 1;
898 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
899 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000900
901 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000902 rtcpbuffer[pos++]=(uint8_t)0;
903 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000904
905 // Add our own SSRC
906 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
907 pos += 4;
908
909 // Add the remote SSRC
910 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
911 pos += 4;
912 return 0;
913}
914
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000915int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000916 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000917 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000918 // sanity
919 if(pos + 20 >= IP_PACKET_SIZE) {
920 return -2;
921 }
922 if (!repeat) {
923 _sequenceNumberFIR++; // do not increase if repetition
924 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000925
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000926 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000927 uint8_t FMT = 4;
928 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
929 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000930
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000931 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000932 rtcpbuffer[pos++] = (uint8_t)0;
933 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000934
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000935 // Add our own SSRC
936 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
937 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000938
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000939 // RFC 5104 4.3.1.2. Semantics
940 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000941 rtcpbuffer[pos++] = (uint8_t)0;
942 rtcpbuffer[pos++] = (uint8_t)0;
943 rtcpbuffer[pos++] = (uint8_t)0;
944 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000945
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000946 // Additional Feedback Control Information (FCI)
947 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
948 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000949
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000950 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
951 rtcpbuffer[pos++] = (uint8_t)0;
952 rtcpbuffer[pos++] = (uint8_t)0;
953 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000954 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000955}
956
957/*
958 0 1 2 3
959 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
960 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
961 | First | Number | PictureID |
962 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
963*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000964int32_t
stefan@webrtc.org717d1472013-07-10 13:39:27 +0000965RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000966{
967 // sanity
968 if(pos + 16 >= IP_PACKET_SIZE)
969 {
970 return -2;
971 }
972 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000973 uint8_t FMT = 2;
974 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
975 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000976
977 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000978 rtcpbuffer[pos++]=(uint8_t)0;
979 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000980
981 // Add our own SSRC
982 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
983 pos += 4;
984
985 // Add the remote SSRC
986 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
987 pos += 4;
988
989 // Add first, number & picture ID 6 bits
990 // first = 0, 13 - bits
991 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000992 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000993 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
994 pos += 4;
995 return 0;
996}
997
998/*
999 0 1 2 3
1000 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
1001 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1002 | PB |0| Payload Type| Native RPSI bit string |
1003 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1004 | defined per codec ... | Padding (0) |
1005 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1006*/
1007/*
1008* Note: not generic made for VP8
1009*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001010int32_t
1011RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
stefan@webrtc.org717d1472013-07-10 13:39:27 +00001012 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001013 const uint64_t pictureID,
1014 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +00001015{
1016 // sanity
1017 if(pos + 24 >= IP_PACKET_SIZE)
1018 {
1019 return -2;
1020 }
1021 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001022 uint8_t FMT = 3;
1023 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1024 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001025
1026 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001027 uint32_t bitsRequired = 7;
1028 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001029 while((pictureID>>bitsRequired) > 0)
1030 {
1031 bitsRequired += 7;
1032 bytesRequired++;
1033 }
1034
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001035 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001036 if(bytesRequired > 6)
1037 {
1038 size = 5;
1039 } else if(bytesRequired > 2)
1040 {
1041 size = 4;
1042 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001043 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001044 rtcpbuffer[pos++]=size;
1045
1046 // Add our own SSRC
1047 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1048 pos += 4;
1049
1050 // Add the remote SSRC
1051 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1052 pos += 4;
1053
1054 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001055 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001056 if(paddingBytes == 4)
1057 {
1058 paddingBytes = 0;
1059 }
1060 // add padding length in bits
1061 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1062 pos++;
1063
1064 // add payload type
1065 rtcpbuffer[pos] = payloadType;
1066 pos++;
1067
1068 // add picture ID
1069 for(int i = bytesRequired-1; i > 0; i--)
1070 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001071 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001072 pos++;
1073 }
1074 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001075 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001076 pos++;
1077
1078 // add padding
1079 for(int j = 0; j <paddingBytes; j++)
1080 {
1081 rtcpbuffer[pos] = 0;
1082 pos++;
1083 }
1084 return 0;
1085}
1086
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001087int32_t
stefan@webrtc.org717d1472013-07-10 13:39:27 +00001088RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001089{
1090 // sanity
1091 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1092 {
1093 return -2;
1094 }
1095 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001096 uint8_t FMT = 15;
1097 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1098 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001099
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001100 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001101 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1102
1103 // Add our own SSRC
1104 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1105 pos += 4;
1106
1107 // Remote SSRC must be 0
1108 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1109 pos += 4;
1110
1111 rtcpbuffer[pos++]='R';
1112 rtcpbuffer[pos++]='E';
1113 rtcpbuffer[pos++]='M';
1114 rtcpbuffer[pos++]='B';
1115
1116 rtcpbuffer[pos++] = _lengthRembSSRC;
1117 // 6 bit Exp
1118 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001119 uint8_t brExp = 0;
1120 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001121 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001122 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001123 {
1124 brExp = i;
1125 break;
1126 }
1127 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001128 const uint32_t brMantissa = (_rembBitrate >> brExp);
1129 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1130 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1131 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001132
1133 for (int i = 0; i < _lengthRembSSRC; i++)
1134 {
1135 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1136 pos += 4;
1137 }
1138 return 0;
1139}
1140
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001141void
1142RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001143{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001144 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001145 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001146}
1147
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001148int32_t
stefan@webrtc.org717d1472013-07-10 13:39:27 +00001149RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001150{
1151 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1152 // If the sender is an owner of the TMMBN -> send TMMBR
1153 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1154
niklase@google.com470e71d2011-07-07 08:21:25 +00001155 // get current bounding set from RTCP receiver
1156 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001157 // store in candidateSet, allocates one extra slot
1158 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001159
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001160 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1161 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1162 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001163 int32_t lengthOfBoundingSet
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001164 = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001165
1166 if(lengthOfBoundingSet > 0)
1167 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001168 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001169 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001170 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1171 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001172 {
1173 // do not send the same tuple
1174 return 0;
1175 }
1176 }
1177 if(!tmmbrOwner)
1178 {
1179 // use received bounding set as candidate set
1180 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001181 candidateSet->SetEntry(lengthOfBoundingSet,
1182 _tmmbr_Send,
1183 _packetOH_Send,
1184 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001185 int numCandidates = lengthOfBoundingSet+ 1;
1186
1187 // find bounding set
1188 TMMBRSet* boundingSet = NULL;
1189 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1190 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1191 {
1192 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1193 }
1194 if(!tmmbrOwner)
1195 {
1196 // did not enter bounding set, no meaning to send this request
1197 return 0;
1198 }
1199 }
1200 }
1201
1202 if(_tmmbr_Send)
1203 {
1204 // sanity
1205 if(pos + 20 >= IP_PACKET_SIZE)
1206 {
1207 return -2;
1208 }
1209 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001210 uint8_t FMT = 3;
1211 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1212 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001213
1214 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001215 rtcpbuffer[pos++]=(uint8_t)0;
1216 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001217
1218 // Add our own SSRC
1219 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1220 pos += 4;
1221
1222 // RFC 5104 4.2.1.2. Semantics
1223
1224 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001225 rtcpbuffer[pos++]=(uint8_t)0;
1226 rtcpbuffer[pos++]=(uint8_t)0;
1227 rtcpbuffer[pos++]=(uint8_t)0;
1228 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001229
1230 // Additional Feedback Control Information (FCI)
1231 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1232 pos += 4;
1233
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001234 uint32_t bitRate = _tmmbr_Send*1000;
1235 uint32_t mmbrExp = 0;
1236 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001237 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001238 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001239 {
1240 mmbrExp = i;
1241 break;
1242 }
1243 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001244 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001245
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001246 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1247 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1248 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1249 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001250 }
1251 return 0;
1252}
1253
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001254int32_t
stefan@webrtc.org717d1472013-07-10 13:39:27 +00001255RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001256{
1257 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1258 if(boundingSet == NULL)
1259 {
1260 return -1;
1261 }
1262 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001263 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001264 {
1265 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1266 return -2;
1267 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001268 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001269 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001270 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1271 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001272
1273 //Add length later
1274 int posLength = pos;
1275 pos++;
1276 pos++;
1277
1278 // Add our own SSRC
1279 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1280 pos += 4;
1281
1282 // RFC 5104 4.2.2.2. Semantics
1283
1284 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001285 rtcpbuffer[pos++]=(uint8_t)0;
1286 rtcpbuffer[pos++]=(uint8_t)0;
1287 rtcpbuffer[pos++]=(uint8_t)0;
1288 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001289
1290 // Additional Feedback Control Information (FCI)
1291 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001292 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001293 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001294 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001295 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001296 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001297 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1298 pos += 4;
1299
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001300 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1301 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001302 for(int i=0; i<64; i++)
1303 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001304 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001305 {
1306 mmbrExp = i;
1307 break;
1308 }
1309 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001310 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1311 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001312
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001313 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1314 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1315 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1316 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001317 numBoundingSet++;
1318 }
1319 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001320 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1321 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1322 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001323 return 0;
1324}
1325
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001326int32_t
stefan@webrtc.org717d1472013-07-10 13:39:27 +00001327RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001328{
1329 // sanity
1330 if(_appData == NULL)
1331 {
1332 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1333 return -1;
1334 }
1335 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1336 {
1337 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1338 return -2;
1339 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001340 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001341
1342 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001343 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001344
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001345 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1346 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1347 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001348
1349 // Add our own SSRC
1350 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1351 pos += 4;
1352
1353 // Add our application name
1354 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1355 pos += 4;
1356
1357 // Add the data
1358 memcpy(rtcpbuffer +pos, _appData,_appLength);
1359 pos += _appLength;
1360 return 0;
1361}
1362
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001363int32_t
1364RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
stefan@webrtc.org717d1472013-07-10 13:39:27 +00001365 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001366 const int32_t nackSize,
1367 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001368 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001369{
1370 // sanity
1371 if(pos + 16 >= IP_PACKET_SIZE)
1372 {
1373 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1374 return -2;
1375 }
1376
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001377 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001378 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001379 uint8_t FMT = 1;
1380 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1381 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001382
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001383 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001384 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001385 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001386
1387 // Add our own SSRC
1388 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1389 pos += 4;
1390
1391 // Add the remote SSRC
1392 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1393 pos += 4;
1394
edjee@google.com79b02892013-04-04 19:43:34 +00001395 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001396 // Build NACK bitmasks and write them to the RTCP message.
1397 // The nack list should be sorted and not contain duplicates if one
1398 // wants to build the smallest rtcp nack packet.
1399 int numOfNackFields = 0;
1400 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1401 (IP_PACKET_SIZE - pos) / 4);
1402 int i = 0;
1403 while (i < nackSize && numOfNackFields < maxNackFields) {
1404 stringBuilder.PushNACK(nackList[i]);
1405 uint16_t nack = nackList[i++];
1406 uint16_t bitmask = 0;
1407 while (i < nackSize) {
1408 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1409 if (shift >= 0 && shift <= 15) {
1410 stringBuilder.PushNACK(nackList[i]);
1411 bitmask |= (1 << shift);
1412 ++i;
1413 } else {
1414 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001415 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001416 }
1417 // Write the sequence number and the bitmask to the packet.
1418 assert(pos + 4 < IP_PACKET_SIZE);
1419 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
1420 pos += 2;
1421 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
1422 pos += 2;
1423 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001424 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001425 if (i != nackSize) {
1426 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1427 "Nack list to large for one packet.");
1428 }
1429 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001430 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001431 return 0;
1432}
1433
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001434int32_t
stefan@webrtc.org717d1472013-07-10 13:39:27 +00001435RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001436{
1437 // sanity
1438 if(pos + 8 >= IP_PACKET_SIZE)
1439 {
1440 return -2;
1441 }
1442 if(_includeCSRCs)
1443 {
1444 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001445 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // 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 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001451
1452 // Add our own SSRC
1453 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1454 pos += 4;
1455
1456 // add CSRCs
1457 for(int i = 0; i < _CSRCs; i++)
1458 {
1459 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1460 pos += 4;
1461 }
1462 } else
1463 {
1464 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001465 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1466 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001467
1468 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001469 rtcpbuffer[pos++]=(uint8_t)0;
1470 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001471
1472 // Add our own SSRC
1473 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1474 pos += 4;
1475 }
1476 return 0;
1477}
1478
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001479int32_t
stefan@webrtc.org717d1472013-07-10 13:39:27 +00001480RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001481{
1482 // sanity
1483 if(pos + 44 >= IP_PACKET_SIZE)
1484 {
1485 return -2;
1486 }
1487
1488 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001489 rtcpbuffer[pos++]=(uint8_t)0x80;
1490 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001491
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001492 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001493
1494 // handle length later on
1495 pos++;
1496 pos++;
1497
1498 // Add our own SSRC
1499 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1500 pos += 4;
1501
1502 // Add a VoIP metrics block
1503 rtcpbuffer[pos++]=7;
1504 rtcpbuffer[pos++]=0;
1505 rtcpbuffer[pos++]=0;
1506 rtcpbuffer[pos++]=8;
1507
1508 // Add the remote SSRC
1509 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1510 pos += 4;
1511
1512 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1513 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1514 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1515 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1516
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001517 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1518 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1519 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1520 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001521
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001522 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1523 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1524 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1525 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001526
1527 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1528 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1529 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1530 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1531
1532 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1533 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1534 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1535 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1536
1537 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1538 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001539 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1540 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001541
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001542 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1543 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1544 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1545 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001546
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001547 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1548 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001549 return 0;
1550}
1551
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001552int32_t
stefan@webrtc.org66b2e5c2013-07-05 14:30:48 +00001553RTCPSender::SendRTCP(
1554 uint32_t packetTypeFlags,
stefan@webrtc.org66b2e5c2013-07-05 14:30:48 +00001555 int32_t nackSize,
1556 const uint16_t* nackList,
1557 bool repeat,
1558 uint64_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +00001559{
stefan@webrtc.org717d1472013-07-10 13:39:27 +00001560 {
1561 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1562 if(_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001563 {
stefan@webrtc.org717d1472013-07-10 13:39:27 +00001564 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1565 "%s invalid state", __FUNCTION__);
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001566 return -1;
1567 }
stefan@webrtc.org717d1472013-07-10 13:39:27 +00001568 }
1569 uint8_t rtcp_buffer[IP_PACKET_SIZE];
1570 int rtcp_length = PrepareRTCP(packetTypeFlags, nackSize, nackList, repeat,
1571 pictureID, rtcp_buffer, IP_PACKET_SIZE);
1572 if (rtcp_length < 0) {
1573 return -1;
1574 }
1575 // Sanity don't send empty packets.
1576 if (rtcp_length == 0)
1577 {
1578 return -1;
1579 }
1580 return SendToNetwork(rtcp_buffer, static_cast<uint16_t>(rtcp_length));
1581}
1582
1583int RTCPSender::PrepareRTCP(
1584 uint32_t packetTypeFlags,
1585 int32_t nackSize,
1586 const uint16_t* nackList,
1587 bool repeat,
1588 uint64_t pictureID,
1589 uint8_t* rtcp_buffer,
1590 int buffer_size) {
1591 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1592 // Collect the received information.
1593 uint32_t NTPsec = 0;
1594 uint32_t NTPfrac = 0;
1595 uint32_t jitterTransmissionOffset = 0;
1596 int position = 0;
1597
1598 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1599
1600 if(_TMMBR ) // Attach TMMBR to send and receive reports.
1601 {
1602 rtcpPacketTypeFlags |= kRtcpTmmbr;
1603 }
1604 if(_appSend)
1605 {
1606 rtcpPacketTypeFlags |= kRtcpApp;
1607 _appSend = false;
1608 }
1609 if(_REMB && _sendREMB)
1610 {
1611 // Always attach REMB to SR if that is configured. Note that REMB is
1612 // only sent on one of the RTP modules in the REMB group.
1613 rtcpPacketTypeFlags |= kRtcpRemb;
1614 }
1615 if(_xrSendVoIPMetric)
1616 {
1617 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1618 _xrSendVoIPMetric = false;
1619 }
1620 if(_sendTMMBN) // Set when having received a TMMBR.
1621 {
1622 rtcpPacketTypeFlags |= kRtcpTmmbn;
1623 _sendTMMBN = false;
1624 }
1625
1626 if(_method == kRtcpCompound)
1627 {
1628 if(_sending)
1629 {
1630 rtcpPacketTypeFlags |= kRtcpSr;
1631 } else
1632 {
1633 rtcpPacketTypeFlags |= kRtcpRr;
1634 }
1635 } else if(_method == kRtcpNonCompound)
1636 {
1637 if(rtcpPacketTypeFlags & kRtcpReport)
1638 {
1639 if(_sending)
1640 {
1641 rtcpPacketTypeFlags |= kRtcpSr;
1642 } else
1643 {
1644 rtcpPacketTypeFlags |= kRtcpRr;
1645 }
1646 }
1647 }
1648 if( rtcpPacketTypeFlags & kRtcpRr ||
1649 rtcpPacketTypeFlags & kRtcpSr)
1650 {
1651 // generate next time to send a RTCP report
1652 // seeded from RTP constructor
1653 int32_t random = rand() % 1000;
1654 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1655
1656 if(_audio)
1657 {
1658 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1659 (RTCP_INTERVAL_AUDIO_MS*random/1000);
1660 }else
1661 {
1662 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1663 if(_sending)
1664 {
1665 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1666 uint32_t sendBitrateKbit = 0;
1667 uint32_t videoRate = 0;
1668 uint32_t fecRate = 0;
1669 uint32_t nackRate = 0;
1670 _rtpRtcp.BitrateSent(&sendBitrateKbit,
1671 &videoRate,
1672 &fecRate,
1673 &nackRate);
1674 sendBitrateKbit /= 1000;
1675 if(sendBitrateKbit != 0)
1676 {
1677 minIntervalMs = 360000/sendBitrateKbit;
1678 }
1679 }
1680 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1681 {
1682 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1683 }
1684 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1685 }
1686 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1687 }
1688
1689 // If the data does not fit in the packet we fill it as much as possible.
1690 int32_t buildVal = 0;
1691
1692 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1693 ReceiveStatistics::StatisticianMap statisticians;
1694 receive_statistics_->GetActiveStatisticians(&statisticians);
elham@webrtc.org6f5707e2013-07-15 20:59:52 +00001695 if (statisticians.empty()) {
1696 // We need to send our NTP even if we dont have received any
1697 // reports.
1698 _clock->CurrentNtp(NTPsec, NTPfrac);
1699 } else {
stefan@webrtc.org717d1472013-07-10 13:39:27 +00001700 ReceiveStatistics::StatisticianMap::const_iterator it;
1701 int i;
1702 for (it = statisticians.begin(), i = 0; it != statisticians.end();
1703 ++it, ++i) {
1704 RTCPReportBlock report_block;
1705 if (PrepareReport(it->second, &report_block, &NTPsec, &NTPfrac))
1706 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1707 }
elham@webrtc.org6f5707e2013-07-15 20:59:52 +00001708 if (_IJ && !statisticians.empty())
1709 {
1710 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
stefan@webrtc.org717d1472013-07-10 13:39:27 +00001711 }
1712 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
1713 }
1714 }
1715
1716 if(rtcpPacketTypeFlags & kRtcpSr)
1717 {
1718 buildVal = BuildSR(rtcp_buffer, position, NTPsec, NTPfrac);
1719 if (buildVal == -1) {
1720 return -1;
1721 } else if (buildVal == -2) {
1722 return position;
1723 }
1724 buildVal = BuildSDEC(rtcp_buffer, position);
1725 if (buildVal == -1) {
1726 return -1;
1727 } else if (buildVal == -2) {
1728 return position;
1729 }
1730 }else if(rtcpPacketTypeFlags & kRtcpRr)
1731 {
1732 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1733 if (buildVal == -1) {
1734 return -1;
1735 } else if (buildVal == -2) {
1736 return position;
1737 }
1738 // only of set
1739 if(_CNAME[0] != 0)
1740 {
1741 buildVal = BuildSDEC(rtcp_buffer, position);
1742 if (buildVal == -1) {
1743 return -1;
1744 }
1745 }
1746 }
1747 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1748 {
1749 // If present, this RTCP packet must be placed after a
1750 // receiver report.
1751 buildVal = BuildExtendedJitterReport(rtcp_buffer,
1752 position,
1753 jitterTransmissionOffset);
1754 if (buildVal == -1) {
1755 return -1;
1756 } else if (buildVal == -2) {
1757 return position;
1758 }
1759 }
1760 if(rtcpPacketTypeFlags & kRtcpPli)
1761 {
1762 buildVal = BuildPLI(rtcp_buffer, position);
1763 if (buildVal == -1) {
1764 return -1;
1765 } else if (buildVal == -2) {
1766 return position;
1767 }
1768 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
1769 _pliCount++;
1770 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC, _pliCount);
1771 }
1772 if(rtcpPacketTypeFlags & kRtcpFir)
1773 {
1774 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1775 if (buildVal == -1) {
1776 return -1;
1777 } else if (buildVal == -2) {
1778 return position;
1779 }
1780 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
1781 _fullIntraRequestCount++;
1782 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
1783 _fullIntraRequestCount);
1784 }
1785 if(rtcpPacketTypeFlags & kRtcpSli)
1786 {
1787 buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1788 if (buildVal == -1) {
1789 return -1;
1790 } else if (buildVal == -2) {
1791 return position;
1792 }
1793 }
1794 if(rtcpPacketTypeFlags & kRtcpRpsi)
1795 {
1796 const int8_t payloadType = _rtpRtcp.SendPayloadType();
1797 if (payloadType == -1) {
1798 return -1;
1799 }
1800 buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1801 (uint8_t)payloadType);
1802 if (buildVal == -1) {
1803 return -1;
1804 } else if (buildVal == -2) {
1805 return position;
1806 }
1807 }
1808 if(rtcpPacketTypeFlags & kRtcpRemb)
1809 {
1810 buildVal = BuildREMB(rtcp_buffer, position);
1811 if (buildVal == -1) {
1812 return -1;
1813 } else if (buildVal == -2) {
1814 return position;
1815 }
1816 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1817 }
1818 if(rtcpPacketTypeFlags & kRtcpBye)
1819 {
1820 buildVal = BuildBYE(rtcp_buffer, position);
1821 if (buildVal == -1) {
1822 return -1;
1823 } else if (buildVal == -2) {
1824 return position;
1825 }
1826 }
1827 if(rtcpPacketTypeFlags & kRtcpApp)
1828 {
1829 buildVal = BuildAPP(rtcp_buffer, position);
1830 if (buildVal == -1) {
1831 return -1;
1832 } else if (buildVal == -2) {
1833 return position;
1834 }
1835 }
1836 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1837 {
1838 buildVal = BuildTMMBR(rtcp_buffer, position);
1839 if (buildVal == -1) {
1840 return -1;
1841 } else if (buildVal == -2) {
1842 return position;
1843 }
1844 }
1845 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1846 {
1847 buildVal = BuildTMMBN(rtcp_buffer, position);
1848 if (buildVal == -1) {
1849 return -1;
1850 } else if (buildVal == -2) {
1851 return position;
1852 }
1853 }
1854 if(rtcpPacketTypeFlags & kRtcpNack)
1855 {
1856 std::string nackString;
1857 buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
1858 &nackString);
1859 if (buildVal == -1) {
1860 return -1;
1861 } else if (buildVal == -2) {
1862 return position;
1863 }
1864 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
1865 "nacks", TRACE_STR_COPY(nackString.c_str()));
1866 _nackCount++;
1867 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC, _nackCount);
1868 }
1869 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1870 {
1871 buildVal = BuildVoIPMetric(rtcp_buffer, position);
1872 if (buildVal == -1) {
1873 return -1;
1874 } else if (buildVal == -2) {
1875 return position;
1876 }
1877 }
1878 return position;
1879}
1880
1881bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
1882 return Status() == kRtcpCompound ||
1883 (rtcp_packet_type & kRtcpReport) ||
1884 (rtcp_packet_type & kRtcpSr) ||
1885 (rtcp_packet_type & kRtcpRr);
1886}
1887
1888bool RTCPSender::PrepareReport(StreamStatistician* statistician,
1889 RTCPReportBlock* report_block,
1890 uint32_t* ntp_secs, uint32_t* ntp_frac) {
1891 // Do we have receive statistics to send?
1892 StreamStatistician::Statistics stats;
1893 if (!statistician->GetStatistics(&stats, true))
1894 return false;
1895 report_block->fractionLost = stats.fraction_lost;
1896 report_block->cumulativeLost = stats.cumulative_lost;
1897 report_block->extendedHighSeqNum =
1898 stats.extended_max_sequence_number;
1899 report_block->jitter = stats.jitter;
1900
1901 uint32_t lastReceivedRRNTPsecs = 0;
1902 uint32_t lastReceivedRRNTPfrac = 0;
1903 uint32_t remoteSR = 0;
1904
1905 // ok even if we have not received a SR, we will send 0 in that case
1906 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1907 lastReceivedRRNTPfrac,
1908 remoteSR);
1909
1910 // get our NTP as late as possible to avoid a race
1911 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
1912
1913 // Delay since last received report
1914 uint32_t delaySinceLastReceivedSR = 0;
1915 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0)) {
1916 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1917 uint32_t now=*ntp_secs&0x0000FFFF;
1918 now <<=16;
1919 now += (*ntp_frac&0xffff0000)>>16;
1920
1921 uint32_t receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
1922 receiveTime <<=16;
1923 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1924
1925 delaySinceLastReceivedSR = now-receiveTime;
1926 }
1927 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
1928 report_block->lastSR = remoteSR;
1929 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001930}
1931
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001932int32_t
1933RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
1934 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001935{
1936 CriticalSectionScoped lock(_criticalSectionTransport);
1937 if(_cbTransport)
1938 {
1939 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1940 {
1941 return 0;
1942 }
1943 }
1944 return -1;
1945}
1946
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001947int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00001948RTCPSender::SetCSRCStatus(const bool include)
1949{
1950 _includeCSRCs = include;
1951 return 0;
1952}
1953
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001954int32_t
1955RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
1956 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00001957{
1958 if(arrLength > kRtpCsrcSize)
1959 {
1960 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1961 assert(false);
1962 return -1;
1963 }
1964
1965 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1966
1967 for(int i = 0; i < arrLength;i++)
1968 {
1969 _CSRC[i] = arrOfCSRC[i];
1970 }
1971 _CSRCs = arrLength;
1972 return 0;
1973}
1974
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001975int32_t
1976RTCPSender::SetApplicationSpecificData(const uint8_t subType,
1977 const uint32_t name,
1978 const uint8_t* data,
1979 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001980{
1981 if(length %4 != 0)
1982 {
1983 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1984 return -1;
1985 }
1986 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1987
1988 if(_appData)
1989 {
1990 delete [] _appData;
1991 }
1992
1993 _appSend = true;
1994 _appSubType = subType;
1995 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001996 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00001997 _appLength = length;
1998 memcpy(_appData, data, length);
1999 return 0;
2000}
2001
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002002int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002003RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2004{
2005 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2006 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2007
2008 _xrSendVoIPMetric = true;
2009 return 0;
2010}
2011
2012// called under critsect _criticalSectionRTCPSender
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002013int32_t RTCPSender::WriteAllReportBlocksToBuffer(
2014 uint8_t* rtcpbuffer,
2015 int pos,
2016 uint8_t& numberOfReportBlocks,
2017 const uint32_t NTPsec,
2018 const uint32_t NTPfrac) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002019 // sanity one block
2020 if(pos + 24 >= IP_PACKET_SIZE) {
2021 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2022 "%s invalid argument", __FUNCTION__);
2023 return -1;
2024 }
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002025 numberOfReportBlocks = external_report_blocks_.size();
2026 numberOfReportBlocks += internal_report_blocks_.size();
2027 if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002028 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2029 "%s invalid argument", __FUNCTION__);
2030 return -1;
2031 }
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002032 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2033 while (!internal_report_blocks_.empty()) {
2034 delete internal_report_blocks_.begin()->second;
2035 internal_report_blocks_.erase(internal_report_blocks_.begin());
2036 }
2037 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2038 return pos;
2039}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002040
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002041int32_t RTCPSender::WriteReportBlocksToBuffer(
2042 uint8_t* rtcpbuffer,
2043 int32_t position,
2044 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2045 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2046 report_blocks.begin();
2047 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002048 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002049 RTCPReportBlock* reportBlock = it->second;
2050 if (reportBlock) {
2051 // Remote SSRC
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002052 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position, remoteSSRC);
2053 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002054
2055 // fraction lost
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002056 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002057
2058 // cumulative loss
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002059 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002060 reportBlock->cumulativeLost);
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002061 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002062
2063 // extended highest seq_no, contain the highest sequence number received
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002064 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002065 reportBlock->extendedHighSeqNum);
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002066 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002067
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002068 // Jitter
2069 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002070 reportBlock->jitter);
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002071 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002072
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002073 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002074 reportBlock->lastSR);
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002075 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002076
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002077 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002078 reportBlock->delaySinceLastSR);
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002079 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002080 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002081 }
stefan@webrtc.org717d1472013-07-10 13:39:27 +00002082 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00002083}
2084
2085// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002086int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002087RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002088 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002089{
2090 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2091
2092 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2093 {
2094 _sendTMMBN = true;
2095 return 0;
2096 }
2097 return -1;
2098}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002099} // namespace webrtc