blob: 55dbd0e859c362ed0c97f228ae0a2a0da3edb632 [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,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +000068 ModuleRtpRtcpImpl* owner) :
niklase@google.com470e71d2011-07-07 08:21:25 +000069 _id(id),
70 _audio(audio),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000071 _clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000072 _method(kRtcpOff),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000073 _rtpRtcp(*owner),
henrike@webrtc.org65573f22011-12-13 19:17:27 +000074 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000075 _cbTransport(NULL),
76
henrike@webrtc.org65573f22011-12-13 19:17:27 +000077 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000078 _usingNack(false),
79 _sending(false),
80 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000081 _REMB(false),
82 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000083 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +000084 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000085 _nextTimeToSendRTCP(0),
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000086 start_timestamp_(0),
87 last_rtp_timestamp_(0),
88 last_frame_capture_time_ms_(-1),
niklase@google.com470e71d2011-07-07 08:21:25 +000089 _SSRC(0),
90 _remoteSSRC(0),
91 _CNAME(),
elham@webrtc.orgb7eda432013-07-15 21:08:27 +000092 _reportBlocks(),
niklase@google.com470e71d2011-07-07 08:21:25 +000093 _csrcCNAMEs(),
94
stefan@webrtc.org7da34592013-04-09 14:56:29 +000095 _cameraDelayMS(0),
96
niklase@google.com470e71d2011-07-07 08:21:25 +000097 _lastSendReport(),
98 _lastRTCPTime(),
99
100 _CSRCs(0),
101 _CSRC(),
102 _includeCSRCs(true),
103
104 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000105
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000106 _lengthRembSSRC(0),
107 _sizeRembSSRC(0),
108 _rembSSRC(NULL),
109 _rembBitrate(0),
110
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000111 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000112 _tmmbr_Send(0),
113 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000114
115 _appSend(false),
116 _appSubType(0),
117 _appName(),
118 _appData(NULL),
119 _appLength(0),
120 _xrSendVoIPMetric(false),
edjee@google.com79b02892013-04-04 19:43:34 +0000121 _xrVoIPMetric(),
122 _nackCount(0),
123 _pliCount(0),
124 _fullIntraRequestCount(0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000125{
126 memset(_CNAME, 0, sizeof(_CNAME));
127 memset(_lastSendReport, 0, sizeof(_lastSendReport));
128 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
129
130 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
131}
132
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000133RTCPSender::~RTCPSender() {
134 delete [] _rembSSRC;
135 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000136
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000137 while (!_reportBlocks.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000138 std::map<uint32_t, RTCPReportBlock*>::iterator it =
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000139 _reportBlocks.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000140 delete it->second;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000141 _reportBlocks.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000142 }
143 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000144 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000145 _csrcCNAMEs.begin();
146 delete it->second;
147 _csrcCNAMEs.erase(it);
148 }
149 delete _criticalSectionTransport;
150 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000151
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000152 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000153}
154
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000155int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000156RTCPSender::Init()
157{
158 CriticalSectionScoped lock(_criticalSectionRTCPSender);
159
160 _method = kRtcpOff;
161 _cbTransport = NULL;
162 _usingNack = false;
163 _sending = false;
164 _sendTMMBN = false;
165 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000166 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000167 _REMB = false;
168 _sendREMB = false;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000169 last_rtp_timestamp_ = 0;
170 last_frame_capture_time_ms_ = -1;
171 start_timestamp_ = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000172 _SSRC = 0;
173 _remoteSSRC = 0;
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000174 _cameraDelayMS = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000175 _sequenceNumberFIR = 0;
176 _tmmbr_Send = 0;
177 _packetOH_Send = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000178 _nextTimeToSendRTCP = 0;
179 _CSRCs = 0;
180 _appSend = false;
181 _appSubType = 0;
182
183 if(_appData)
184 {
185 delete [] _appData;
186 _appData = NULL;
187 }
188 _appLength = 0;
189
190 _xrSendVoIPMetric = false;
191
192 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
193 memset(_CNAME, 0, sizeof(_CNAME));
194 memset(_lastSendReport, 0, sizeof(_lastSendReport));
195 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
edjee@google.com79b02892013-04-04 19:43:34 +0000196
197 _nackCount = 0;
198 _pliCount = 0;
199 _fullIntraRequestCount = 0;
200
niklase@google.com470e71d2011-07-07 08:21:25 +0000201 return 0;
202}
203
204void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000205RTCPSender::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +0000206{
207 _id = id;
208}
209
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000210int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000211RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
212{
213 CriticalSectionScoped lock(_criticalSectionTransport);
214 _cbTransport = outgoingTransport;
215 return 0;
216}
217
218RTCPMethod
219RTCPSender::Status() const
220{
221 CriticalSectionScoped lock(_criticalSectionRTCPSender);
222 return _method;
223}
224
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000225int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000226RTCPSender::SetRTCPStatus(const RTCPMethod method)
227{
228 CriticalSectionScoped lock(_criticalSectionRTCPSender);
229 if(method != kRtcpOff)
230 {
231 if(_audio)
232 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000233 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000234 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000235 } else
236 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000237 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000238 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000239 }
240 }
241 _method = method;
242 return 0;
243}
244
245bool
246RTCPSender::Sending() const
247{
248 CriticalSectionScoped lock(_criticalSectionRTCPSender);
249 return _sending;
250}
251
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000252int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000253RTCPSender::SetSendingStatus(const bool sending)
254{
255 bool sendRTCPBye = false;
256 {
257 CriticalSectionScoped lock(_criticalSectionRTCPSender);
258
259 if(_method != kRtcpOff)
260 {
261 if(sending == false && _sending == true)
262 {
263 // Trigger RTCP bye
264 sendRTCPBye = true;
265 }
266 }
267 _sending = sending;
268 }
269 if(sendRTCPBye)
270 {
tnakamura@webrtc.orgaa4d96a2013-07-16 19:25:04 +0000271 return SendRTCP(kRtcpBye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000272 }
273 return 0;
274}
275
276bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000277RTCPSender::REMB() const
278{
279 CriticalSectionScoped lock(_criticalSectionRTCPSender);
280 return _REMB;
281}
282
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000283int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000284RTCPSender::SetREMBStatus(const bool enable)
285{
286 CriticalSectionScoped lock(_criticalSectionRTCPSender);
287 _REMB = enable;
288 return 0;
289}
290
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000291int32_t
292RTCPSender::SetREMBData(const uint32_t bitrate,
293 const uint8_t numberOfSSRC,
294 const uint32_t* SSRC)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000295{
296 CriticalSectionScoped lock(_criticalSectionRTCPSender);
297 _rembBitrate = bitrate;
298
299 if(_sizeRembSSRC < numberOfSSRC)
300 {
301 delete [] _rembSSRC;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000302 _rembSSRC = new uint32_t[numberOfSSRC];
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000303 _sizeRembSSRC = numberOfSSRC;
304 }
305
306 _lengthRembSSRC = numberOfSSRC;
307 for (int i = 0; i < numberOfSSRC; i++)
308 {
309 _rembSSRC[i] = SSRC[i];
310 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000311 _sendREMB = true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000312 return 0;
313}
314
315bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000316RTCPSender::TMMBR() const
317{
318 CriticalSectionScoped lock(_criticalSectionRTCPSender);
319 return _TMMBR;
320}
321
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000322int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000323RTCPSender::SetTMMBRStatus(const bool enable)
324{
325 CriticalSectionScoped lock(_criticalSectionRTCPSender);
326 _TMMBR = enable;
327 return 0;
328}
329
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000330bool
331RTCPSender::IJ() const
332{
333 CriticalSectionScoped lock(_criticalSectionRTCPSender);
334 return _IJ;
335}
336
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000337int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000338RTCPSender::SetIJStatus(const bool enable)
339{
340 CriticalSectionScoped lock(_criticalSectionRTCPSender);
341 _IJ = enable;
342 return 0;
343}
344
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000345void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
346 start_timestamp_ = start_timestamp;
347}
348
349void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
350 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000351 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000352 last_rtp_timestamp_ = rtp_timestamp;
353 if (capture_time_ms < 0) {
354 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000355 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000356 } else {
357 last_frame_capture_time_ms_ = capture_time_ms;
358 }
359}
360
niklase@google.com470e71d2011-07-07 08:21:25 +0000361void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000362RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000363{
364 CriticalSectionScoped lock(_criticalSectionRTCPSender);
365
366 if(_SSRC != 0)
367 {
368 // not first SetSSRC, probably due to a collision
369 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000370 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000371 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000372 }
373 _SSRC = ssrc;
374}
375
tnakamura@webrtc.orgaa4d96a2013-07-16 19:25:04 +0000376int32_t
377RTCPSender::SetRemoteSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000378{
379 CriticalSectionScoped lock(_criticalSectionRTCPSender);
380 _remoteSSRC = ssrc;
tnakamura@webrtc.orgaa4d96a2013-07-16 19:25:04 +0000381 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000382}
383
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000384int32_t
385RTCPSender::SetCameraDelay(const int32_t delayMS)
386{
387 CriticalSectionScoped lock(_criticalSectionRTCPSender);
388 if(delayMS > 1000 || delayMS < -1000)
389 {
390 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
391 return -1;
392 }
393 _cameraDelayMS = delayMS;
394 return 0;
395}
396
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000397int32_t RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000398 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000399 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000400 cName[RTCP_CNAME_SIZE - 1] = 0;
401 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000402 return 0;
403}
404
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000405int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000406 if (!cName)
407 return -1;
408
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000409 CriticalSectionScoped lock(_criticalSectionRTCPSender);
410 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
411 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
412 return 0;
413}
414
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000415int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
416 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000417 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000418 CriticalSectionScoped lock(_criticalSectionRTCPSender);
419 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
420 return -1;
421 }
422 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000423 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
424 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000425 _csrcCNAMEs[SSRC] = ptr;
426 return 0;
427}
428
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000429int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000430 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000431 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000432 _csrcCNAMEs.find(SSRC);
433
434 if (it == _csrcCNAMEs.end()) {
435 return -1;
436 }
437 delete it->second;
438 _csrcCNAMEs.erase(it);
439 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000440}
441
442bool
443RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
444{
445/*
446 For audio we use a fix 5 sec interval
447
448 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
449 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
450
451
452From RFC 3550
453
454 MAX RTCP BW is 5% if the session BW
455 A send report is approximately 65 bytes inc CNAME
456 A report report is approximately 28 bytes
457
458 The RECOMMENDED value for the reduced minimum in seconds is 360
459 divided by the session bandwidth in kilobits/second. This minimum
460 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
461
462 If the participant has not yet sent an RTCP packet (the variable
463 initial is true), the constant Tmin is set to 2.5 seconds, else it
464 is set to 5 seconds.
465
466 The interval between RTCP packets is varied randomly over the
467 range [0.5,1.5] times the calculated interval to avoid unintended
468 synchronization of all participants
469
470 if we send
471 If the participant is a sender (we_sent true), the constant C is
472 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
473 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
474 number of senders.
475
476 if we receive only
477 If we_sent is not true, the constant C is set
478 to the average RTCP packet size divided by 75% of the RTCP
479 bandwidth. The constant n is set to the number of receivers
480 (members - senders). If the number of senders is greater than
481 25%, senders and receivers are treated together.
482
483 reconsideration NOT required for peer-to-peer
484 "timer reconsideration" is
485 employed. This algorithm implements a simple back-off mechanism
486 which causes users to hold back RTCP packet transmission if the
487 group sizes are increasing.
488
489 n = number of members
490 C = avg_size/(rtcpBW/4)
491
492 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
493
494 4. The calculated interval T is set to a number uniformly distributed
495 between 0.5 and 1.5 times the deterministic calculated interval.
496
497 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
498 for the fact that the timer reconsideration algorithm converges to
499 a value of the RTCP bandwidth below the intended average
500*/
501
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000502 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000503
504 CriticalSectionScoped lock(_criticalSectionRTCPSender);
505
niklase@google.com470e71d2011-07-07 08:21:25 +0000506 if(_method == kRtcpOff)
507 {
508 return false;
509 }
510
niklase@google.com470e71d2011-07-07 08:21:25 +0000511 if(!_audio && sendKeyframeBeforeRTP)
512 {
513 // for video key-frames we want to send the RTCP before the large key-frame
514 // if we have a 100 ms margin
515 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
516 }
517
518 if(now > _nextTimeToSendRTCP)
519 {
520 return true;
521
522 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
523 {
524 // wrap
525 return true;
526 }
527 return false;
528}
529
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000530uint32_t
531RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000532{
533 CriticalSectionScoped lock(_criticalSectionRTCPSender);
534
535 lastRTCPTime = _lastRTCPTime[0];
536 return _lastSendReport[0];
537}
538
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000539uint32_t
540RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000541{
542 CriticalSectionScoped lock(_criticalSectionRTCPSender);
543
544 // This is only saved when we are the sender
545 if((_lastSendReport[0] == 0) || (sendReport == 0))
546 {
547 return 0; // will be ignored
548 } else
549 {
550 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
551 {
552 if( _lastSendReport[i] == sendReport)
553 {
554 return _lastRTCPTime[i];
555 }
556 }
557 }
558 return 0;
559}
560
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000561int32_t RTCPSender::AddReportBlock(const uint32_t SSRC,
562 const RTCPReportBlock* reportBlock) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000563 if (reportBlock == NULL) {
564 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
565 "%s invalid argument", __FUNCTION__);
566 return -1;
567 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000568 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000569
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000570 if (_reportBlocks.size() >= RTCP_MAX_REPORT_BLOCKS) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000571 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
572 "%s invalid argument", __FUNCTION__);
573 return -1;
574 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000575 std::map<uint32_t, RTCPReportBlock*>::iterator it =
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000576 _reportBlocks.find(SSRC);
577 if (it != _reportBlocks.end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000578 delete it->second;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000579 _reportBlocks.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));
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000583 _reportBlocks[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000584 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000585}
586
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000587int32_t RTCPSender::RemoveReportBlock(const 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 =
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000591 _reportBlocks.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000592
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000593 if (it == _reportBlocks.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;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000597 _reportBlocks.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.org2f446732013-04-08 11:08:41 +0000601int32_t
602RTCPSender::BuildSR(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000603 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000604 const uint32_t NTPsec,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000605 const uint32_t NTPfrac,
606 const RTCPReportBlock* received)
niklase@google.com470e71d2011-07-07 08:21:25 +0000607{
608 // sanity
609 if(pos + 52 >= IP_PACKET_SIZE)
610 {
611 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
612 return -2;
613 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000614 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000615
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000616 uint32_t posNumberOfReportBlocks = pos;
617 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000618
619 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000620 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000621
622 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
623 {
624 // shift old
625 _lastSendReport[i+1] = _lastSendReport[i];
626 _lastRTCPTime[i+1] =_lastRTCPTime[i];
627 }
628
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000629 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000630 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000631
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000632 uint32_t freqHz = 90000; // For video
633 if(_audio) {
634 freqHz = _rtpRtcp.CurrentSendFrequencyHz();
niklase@google.com470e71d2011-07-07 08:21:25 +0000635 }
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000636
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000637 // The timestamp of this RTCP packet should be estimated as the timestamp of
638 // the frame being captured at this moment. We are calculating that
639 // timestamp as the last frame's timestamp + the time since the last frame
640 // was captured.
641 {
642 // Needs protection since this method is called on the process thread.
643 CriticalSectionScoped lock(_criticalSectionRTCPSender);
644 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
645 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
646 (freqHz / 1000);
647 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000648
649 // Add sender data
650 // Save for our length field
651 pos++;
652 pos++;
653
654 // Add our own SSRC
655 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
656 pos += 4;
657 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000658 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000659 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000660 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000661 pos += 4;
662 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
663 pos += 4;
664
665 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000666 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000667 pos += 4;
668
669 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000670 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000671 pos += 4;
672
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000673 uint8_t numberOfReportBlocks = 0;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000674 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000675 if(retVal < 0)
676 {
677 //
678 return retVal ;
679 }
680 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
681
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000682 uint16_t len = uint16_t((pos/4) -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000683 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
684 return 0;
685}
686
687
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000688int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000689 uint32_t& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000690 size_t lengthCname = strlen(_CNAME);
691 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000692
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000693 // sanity
694 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
695 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
696 "%s invalid argument", __FUNCTION__);
697 return -2;
698 }
699 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000700
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000701 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000702 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
703 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000704
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000705 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000706 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000707 pos++;
708 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000709
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000710 // Add our own SSRC
711 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
712 pos += 4;
713
714 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000715 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000716
717 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000718 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000719
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000720 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000721
722 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
723 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000724 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000725
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000726 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000727 // We must have a zero field even if we have an even multiple of 4 bytes
728 if ((pos % 4) == 0) {
729 padding++;
730 rtcpbuffer[pos++]=0;
731 }
732 while ((pos % 4) != 0) {
733 padding++;
734 rtcpbuffer[pos++]=0;
735 }
736 SDESLength += padding;
737
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000738 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000739 _csrcCNAMEs.begin();
740
741 for(; it != _csrcCNAMEs.end(); it++) {
742 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000743 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000744
745 // Add SSRC
746 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000747 pos += 4;
748
749 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000750 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000751
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000752 size_t length = strlen(cname->name);
753 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000754
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000755 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000756 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000757
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000758 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000759
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000760 pos += length;
761 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000762 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000763
764 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000765 if((pos % 4) == 0){
766 padding++;
767 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000768 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000769 while((pos % 4) != 0){
770 padding++;
771 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000772 }
773 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000774 }
775 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000776 uint16_t buffer_length = (SDESLength / 4) - 1;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000777 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
778 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000779 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000780}
781
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000782int32_t
783RTCPSender::BuildRR(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000784 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000785 const uint32_t NTPsec,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000786 const uint32_t NTPfrac,
787 const RTCPReportBlock* received)
niklase@google.com470e71d2011-07-07 08:21:25 +0000788{
789 // sanity one block
790 if(pos + 32 >= IP_PACKET_SIZE)
791 {
792 return -2;
793 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000794 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000795
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000796 rtcpbuffer[pos++]=(uint8_t)0x80;
797 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000798
799 // Save for our length field
800 pos++;
801 pos++;
802
803 // Add our own SSRC
804 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
805 pos += 4;
806
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000807 uint8_t numberOfReportBlocks = 0;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000808 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000809 if(retVal < 0)
810 {
811 return retVal;
812 }
813 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
814
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000815 uint16_t len = uint16_t((pos)/4 -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000816 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
817 return 0;
818}
819
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000820// From RFC 5450: Transmission Time Offsets in RTP Streams.
821// 0 1 2 3
822// 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
823// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
824// hdr |V=2|P| RC | PT=IJ=195 | length |
825// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
826// | inter-arrival jitter |
827// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
828// . .
829// . .
830// . .
831// | inter-arrival jitter |
832// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
833//
834// If present, this RTCP packet must be placed after a receiver report
835// (inside a compound RTCP packet), and MUST have the same value for RC
836// (reception report count) as the receiver report.
837
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000838int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000839RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000840 uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000841 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000842 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000843{
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000844 if (_reportBlocks.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000845 {
846 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
847 return 0;
848 }
849
850 // sanity
851 if(pos + 8 >= IP_PACKET_SIZE)
852 {
853 return -2;
854 }
855 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000856 uint8_t RC = 1;
857 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
858 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000859
860 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000861 rtcpbuffer[pos++]=(uint8_t)0;
862 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000863
864 // Add inter-arrival jitter
865 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
866 jitterTransmissionTimeOffset);
867 pos += 4;
868 return 0;
869}
870
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000871int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000872RTCPSender::BuildPLI(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000873{
874 // sanity
875 if(pos + 12 >= IP_PACKET_SIZE)
876 {
877 return -2;
878 }
879 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000880 uint8_t FMT = 1;
881 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
882 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000883
884 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000885 rtcpbuffer[pos++]=(uint8_t)0;
886 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000887
888 // Add our own SSRC
889 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
890 pos += 4;
891
892 // Add the remote SSRC
893 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
894 pos += 4;
895 return 0;
896}
897
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000898int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000899 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000900 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000901 // sanity
902 if(pos + 20 >= IP_PACKET_SIZE) {
903 return -2;
904 }
905 if (!repeat) {
906 _sequenceNumberFIR++; // do not increase if repetition
907 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000908
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000909 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000910 uint8_t FMT = 4;
911 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
912 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000913
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000914 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000915 rtcpbuffer[pos++] = (uint8_t)0;
916 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000917
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000918 // Add our own SSRC
919 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
920 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000921
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000922 // RFC 5104 4.3.1.2. Semantics
923 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000924 rtcpbuffer[pos++] = (uint8_t)0;
925 rtcpbuffer[pos++] = (uint8_t)0;
926 rtcpbuffer[pos++] = (uint8_t)0;
927 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000928
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000929 // Additional Feedback Control Information (FCI)
930 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
931 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000932
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000933 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
934 rtcpbuffer[pos++] = (uint8_t)0;
935 rtcpbuffer[pos++] = (uint8_t)0;
936 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000937 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000938}
939
940/*
941 0 1 2 3
942 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
943 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
944 | First | Number | PictureID |
945 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
946*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000947int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000948RTCPSender::BuildSLI(uint8_t* rtcpbuffer, uint32_t& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000949{
950 // sanity
951 if(pos + 16 >= IP_PACKET_SIZE)
952 {
953 return -2;
954 }
955 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000956 uint8_t FMT = 2;
957 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
958 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000959
960 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000961 rtcpbuffer[pos++]=(uint8_t)0;
962 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000963
964 // Add our own SSRC
965 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
966 pos += 4;
967
968 // Add the remote SSRC
969 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
970 pos += 4;
971
972 // Add first, number & picture ID 6 bits
973 // first = 0, 13 - bits
974 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000975 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000976 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
977 pos += 4;
978 return 0;
979}
980
981/*
982 0 1 2 3
983 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
984 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
985 | PB |0| Payload Type| Native RPSI bit string |
986 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
987 | defined per codec ... | Padding (0) |
988 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
989*/
990/*
991* Note: not generic made for VP8
992*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000993int32_t
994RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000995 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000996 const uint64_t pictureID,
997 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +0000998{
999 // sanity
1000 if(pos + 24 >= IP_PACKET_SIZE)
1001 {
1002 return -2;
1003 }
1004 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001005 uint8_t FMT = 3;
1006 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1007 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001008
1009 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001010 uint32_t bitsRequired = 7;
1011 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001012 while((pictureID>>bitsRequired) > 0)
1013 {
1014 bitsRequired += 7;
1015 bytesRequired++;
1016 }
1017
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001018 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001019 if(bytesRequired > 6)
1020 {
1021 size = 5;
1022 } else if(bytesRequired > 2)
1023 {
1024 size = 4;
1025 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001026 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001027 rtcpbuffer[pos++]=size;
1028
1029 // Add our own SSRC
1030 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1031 pos += 4;
1032
1033 // Add the remote SSRC
1034 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1035 pos += 4;
1036
1037 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001038 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001039 if(paddingBytes == 4)
1040 {
1041 paddingBytes = 0;
1042 }
1043 // add padding length in bits
1044 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1045 pos++;
1046
1047 // add payload type
1048 rtcpbuffer[pos] = payloadType;
1049 pos++;
1050
1051 // add picture ID
1052 for(int i = bytesRequired-1; i > 0; i--)
1053 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001054 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001055 pos++;
1056 }
1057 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001058 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001059 pos++;
1060
1061 // add padding
1062 for(int j = 0; j <paddingBytes; j++)
1063 {
1064 rtcpbuffer[pos] = 0;
1065 pos++;
1066 }
1067 return 0;
1068}
1069
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001070int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001071RTCPSender::BuildREMB(uint8_t* rtcpbuffer, uint32_t& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001072{
1073 // sanity
1074 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1075 {
1076 return -2;
1077 }
1078 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001079 uint8_t FMT = 15;
1080 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1081 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001082
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001083 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001084 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1085
1086 // Add our own SSRC
1087 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1088 pos += 4;
1089
1090 // Remote SSRC must be 0
1091 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1092 pos += 4;
1093
1094 rtcpbuffer[pos++]='R';
1095 rtcpbuffer[pos++]='E';
1096 rtcpbuffer[pos++]='M';
1097 rtcpbuffer[pos++]='B';
1098
1099 rtcpbuffer[pos++] = _lengthRembSSRC;
1100 // 6 bit Exp
1101 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001102 uint8_t brExp = 0;
1103 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001104 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001105 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001106 {
1107 brExp = i;
1108 break;
1109 }
1110 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001111 const uint32_t brMantissa = (_rembBitrate >> brExp);
1112 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1113 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1114 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001115
1116 for (int i = 0; i < _lengthRembSSRC; i++)
1117 {
1118 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1119 pos += 4;
1120 }
1121 return 0;
1122}
1123
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001124void
1125RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001126{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001127 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001128 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001129}
1130
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001131int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001132RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001133{
1134 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1135 // If the sender is an owner of the TMMBN -> send TMMBR
1136 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1137
niklase@google.com470e71d2011-07-07 08:21:25 +00001138 // get current bounding set from RTCP receiver
1139 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001140 // store in candidateSet, allocates one extra slot
1141 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001142
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001143 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1144 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1145 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001146 int32_t lengthOfBoundingSet
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001147 = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001148
1149 if(lengthOfBoundingSet > 0)
1150 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001151 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001152 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001153 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1154 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001155 {
1156 // do not send the same tuple
1157 return 0;
1158 }
1159 }
1160 if(!tmmbrOwner)
1161 {
1162 // use received bounding set as candidate set
1163 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001164 candidateSet->SetEntry(lengthOfBoundingSet,
1165 _tmmbr_Send,
1166 _packetOH_Send,
1167 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001168 int numCandidates = lengthOfBoundingSet+ 1;
1169
1170 // find bounding set
1171 TMMBRSet* boundingSet = NULL;
1172 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1173 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1174 {
1175 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1176 }
1177 if(!tmmbrOwner)
1178 {
1179 // did not enter bounding set, no meaning to send this request
1180 return 0;
1181 }
1182 }
1183 }
1184
1185 if(_tmmbr_Send)
1186 {
1187 // sanity
1188 if(pos + 20 >= IP_PACKET_SIZE)
1189 {
1190 return -2;
1191 }
1192 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001193 uint8_t FMT = 3;
1194 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1195 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001196
1197 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001198 rtcpbuffer[pos++]=(uint8_t)0;
1199 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001200
1201 // Add our own SSRC
1202 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1203 pos += 4;
1204
1205 // RFC 5104 4.2.1.2. Semantics
1206
1207 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001208 rtcpbuffer[pos++]=(uint8_t)0;
1209 rtcpbuffer[pos++]=(uint8_t)0;
1210 rtcpbuffer[pos++]=(uint8_t)0;
1211 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001212
1213 // Additional Feedback Control Information (FCI)
1214 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1215 pos += 4;
1216
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001217 uint32_t bitRate = _tmmbr_Send*1000;
1218 uint32_t mmbrExp = 0;
1219 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001220 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001221 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001222 {
1223 mmbrExp = i;
1224 break;
1225 }
1226 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001227 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001228
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001229 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1230 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1231 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1232 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001233 }
1234 return 0;
1235}
1236
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001237int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001238RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001239{
1240 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1241 if(boundingSet == NULL)
1242 {
1243 return -1;
1244 }
1245 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001246 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001247 {
1248 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1249 return -2;
1250 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001251 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001252 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001253 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1254 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001255
1256 //Add length later
1257 int posLength = pos;
1258 pos++;
1259 pos++;
1260
1261 // Add our own SSRC
1262 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1263 pos += 4;
1264
1265 // RFC 5104 4.2.2.2. Semantics
1266
1267 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001268 rtcpbuffer[pos++]=(uint8_t)0;
1269 rtcpbuffer[pos++]=(uint8_t)0;
1270 rtcpbuffer[pos++]=(uint8_t)0;
1271 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001272
1273 // Additional Feedback Control Information (FCI)
1274 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001275 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001276 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001277 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001278 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001279 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001280 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1281 pos += 4;
1282
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001283 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1284 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001285 for(int i=0; i<64; i++)
1286 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001287 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001288 {
1289 mmbrExp = i;
1290 break;
1291 }
1292 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001293 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1294 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001295
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001296 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1297 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1298 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1299 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001300 numBoundingSet++;
1301 }
1302 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001303 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1304 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1305 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001306 return 0;
1307}
1308
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001309int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001310RTCPSender::BuildAPP(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001311{
1312 // sanity
1313 if(_appData == NULL)
1314 {
1315 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1316 return -1;
1317 }
1318 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1319 {
1320 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1321 return -2;
1322 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001323 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001324
1325 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001326 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001327
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001328 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1329 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1330 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001331
1332 // Add our own SSRC
1333 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1334 pos += 4;
1335
1336 // Add our application name
1337 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1338 pos += 4;
1339
1340 // Add the data
1341 memcpy(rtcpbuffer +pos, _appData,_appLength);
1342 pos += _appLength;
1343 return 0;
1344}
1345
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001346int32_t
1347RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001348 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001349 const int32_t nackSize,
1350 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001351 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001352{
1353 // sanity
1354 if(pos + 16 >= IP_PACKET_SIZE)
1355 {
1356 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1357 return -2;
1358 }
1359
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001360 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001361 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001362 uint8_t FMT = 1;
1363 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1364 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001365
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001366 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001367 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001368 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001369
1370 // Add our own SSRC
1371 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1372 pos += 4;
1373
1374 // Add the remote SSRC
1375 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1376 pos += 4;
1377
edjee@google.com79b02892013-04-04 19:43:34 +00001378 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001379 // Build NACK bitmasks and write them to the RTCP message.
1380 // The nack list should be sorted and not contain duplicates if one
1381 // wants to build the smallest rtcp nack packet.
1382 int numOfNackFields = 0;
1383 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1384 (IP_PACKET_SIZE - pos) / 4);
1385 int i = 0;
1386 while (i < nackSize && numOfNackFields < maxNackFields) {
1387 stringBuilder.PushNACK(nackList[i]);
1388 uint16_t nack = nackList[i++];
1389 uint16_t bitmask = 0;
1390 while (i < nackSize) {
1391 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1392 if (shift >= 0 && shift <= 15) {
1393 stringBuilder.PushNACK(nackList[i]);
1394 bitmask |= (1 << shift);
1395 ++i;
1396 } else {
1397 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001398 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001399 }
1400 // Write the sequence number and the bitmask to the packet.
1401 assert(pos + 4 < IP_PACKET_SIZE);
1402 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
1403 pos += 2;
1404 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
1405 pos += 2;
1406 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001407 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001408 if (i != nackSize) {
1409 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1410 "Nack list to large for one packet.");
1411 }
1412 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001413 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001414 return 0;
1415}
1416
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001417int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001418RTCPSender::BuildBYE(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001419{
1420 // sanity
1421 if(pos + 8 >= IP_PACKET_SIZE)
1422 {
1423 return -2;
1424 }
1425 if(_includeCSRCs)
1426 {
1427 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001428 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1429 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001430
1431 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001432 rtcpbuffer[pos++]=(uint8_t)0;
1433 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001434
1435 // Add our own SSRC
1436 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1437 pos += 4;
1438
1439 // add CSRCs
1440 for(int i = 0; i < _CSRCs; i++)
1441 {
1442 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1443 pos += 4;
1444 }
1445 } else
1446 {
1447 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001448 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1449 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001450
1451 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001452 rtcpbuffer[pos++]=(uint8_t)0;
1453 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001454
1455 // Add our own SSRC
1456 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1457 pos += 4;
1458 }
1459 return 0;
1460}
1461
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001462int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001463RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001464{
1465 // sanity
1466 if(pos + 44 >= IP_PACKET_SIZE)
1467 {
1468 return -2;
1469 }
1470
1471 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001472 rtcpbuffer[pos++]=(uint8_t)0x80;
1473 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001474
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001475 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001476
1477 // handle length later on
1478 pos++;
1479 pos++;
1480
1481 // Add our own SSRC
1482 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1483 pos += 4;
1484
1485 // Add a VoIP metrics block
1486 rtcpbuffer[pos++]=7;
1487 rtcpbuffer[pos++]=0;
1488 rtcpbuffer[pos++]=0;
1489 rtcpbuffer[pos++]=8;
1490
1491 // Add the remote SSRC
1492 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1493 pos += 4;
1494
1495 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1496 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1497 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1498 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1499
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001500 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1501 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1502 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1503 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001504
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001505 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1506 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1507 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1508 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001509
1510 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1511 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1512 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1513 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1514
1515 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1516 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1517 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1518 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1519
1520 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1521 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001522 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1523 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001524
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001525 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1526 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1527 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1528 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001529
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001530 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1531 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001532 return 0;
1533}
1534
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001535int32_t
tnakamura@webrtc.orgaa4d96a2013-07-16 19:25:04 +00001536RTCPSender::SendRTCP(const uint32_t packetTypeFlags,
1537 const int32_t nackSize, // NACK
1538 const uint16_t* nackList, // NACK
1539 const bool repeat, // FIR
1540 const uint64_t pictureID) // SLI & RPSI
niklase@google.com470e71d2011-07-07 08:21:25 +00001541{
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001542 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1543 uint32_t pos = 0;
1544 uint8_t rtcpbuffer[IP_PACKET_SIZE];
1545
1546 do // only to be able to use break :) (and the critsect must be inside its own scope)
niklase@google.com470e71d2011-07-07 08:21:25 +00001547 {
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001548 // collect the received information
1549 RTCPReportBlock received;
1550 bool hasReceived = false;
1551 uint32_t NTPsec = 0;
1552 uint32_t NTPfrac = 0;
1553 bool rtcpCompound = false;
1554 uint32_t jitterTransmissionOffset = 0;
1555
1556 {
1557 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1558 if(_method == kRtcpOff)
1559 {
1560 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1561 "%s invalid state", __FUNCTION__);
1562 return -1;
1563 }
1564 rtcpCompound = (_method == kRtcpCompound) ? true : false;
1565 }
1566
1567 if (rtcpCompound ||
1568 rtcpPacketTypeFlags & kRtcpReport ||
1569 rtcpPacketTypeFlags & kRtcpSr ||
1570 rtcpPacketTypeFlags & kRtcpRr)
1571 {
tnakamura@webrtc.orgaa4d96a2013-07-16 19:25:04 +00001572 // get statistics from our RTPreceiver outside critsect
1573 if(_rtpRtcp.ReportBlockStatistics(&received.fractionLost,
1574 &received.cumulativeLost,
1575 &received.extendedHighSeqNum,
1576 &received.jitter,
1577 &jitterTransmissionOffset) == 0)
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001578 {
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001579 hasReceived = true;
1580
1581 uint32_t lastReceivedRRNTPsecs = 0;
1582 uint32_t lastReceivedRRNTPfrac = 0;
1583 uint32_t remoteSR = 0;
1584
1585 // ok even if we have not received a SR, we will send 0 in that case
1586 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1587 lastReceivedRRNTPfrac,
1588 remoteSR);
1589
1590 // get our NTP as late as possible to avoid a race
1591 _clock->CurrentNtp(NTPsec, NTPfrac);
1592
1593 // Delay since last received report
1594 uint32_t delaySinceLastReceivedSR = 0;
1595 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
1596 {
1597 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1598 uint32_t now=NTPsec&0x0000FFFF;
1599 now <<=16;
1600 now += (NTPfrac&0xffff0000)>>16;
1601
1602 uint32_t receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
1603 receiveTime <<=16;
1604 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1605
1606 delaySinceLastReceivedSR = now-receiveTime;
1607 }
1608 received.delaySinceLastSR = delaySinceLastReceivedSR;
1609 received.lastSR = remoteSR;
1610 } else
1611 {
1612 // we need to send our NTP even if we dont have received any reports
1613 _clock->CurrentNtp(NTPsec, NTPfrac);
1614 }
1615 }
1616
1617 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1618
1619 if(_TMMBR ) // attach TMMBR to send and receive reports
1620 {
1621 rtcpPacketTypeFlags |= kRtcpTmmbr;
1622 }
1623 if(_appSend)
1624 {
1625 rtcpPacketTypeFlags |= kRtcpApp;
1626 _appSend = false;
1627 }
1628 if(_REMB && _sendREMB)
1629 {
1630 // Always attach REMB to SR if that is configured. Note that REMB is
1631 // only sent on one of the RTP modules in the REMB group.
1632 rtcpPacketTypeFlags |= kRtcpRemb;
1633 }
1634 if(_xrSendVoIPMetric)
1635 {
1636 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1637 _xrSendVoIPMetric = false;
1638 }
1639 if(_sendTMMBN) // set when having received a TMMBR
1640 {
1641 rtcpPacketTypeFlags |= kRtcpTmmbn;
1642 _sendTMMBN = false;
1643 }
1644
1645 if(_method == kRtcpCompound)
1646 {
1647 if(_sending)
1648 {
1649 rtcpPacketTypeFlags |= kRtcpSr;
1650 } else
1651 {
1652 rtcpPacketTypeFlags |= kRtcpRr;
1653 }
1654 if (_IJ && hasReceived)
1655 {
1656 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1657 }
1658 } else if(_method == kRtcpNonCompound)
1659 {
1660 if(rtcpPacketTypeFlags & kRtcpReport)
1661 {
1662 if(_sending)
1663 {
1664 rtcpPacketTypeFlags |= kRtcpSr;
1665 } else
1666 {
1667 rtcpPacketTypeFlags |= kRtcpRr;
1668 }
1669 }
1670 }
1671 if( rtcpPacketTypeFlags & kRtcpRr ||
1672 rtcpPacketTypeFlags & kRtcpSr)
1673 {
1674 // generate next time to send a RTCP report
1675 // seeded from RTP constructor
1676 int32_t random = rand() % 1000;
1677 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1678
1679 if(_audio)
1680 {
1681 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
1682 }else
1683 {
1684 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1685 if(_sending)
1686 {
1687 // calc bw for video 360/sendBW in kbit/s
1688 uint32_t sendBitrateKbit = 0;
1689 uint32_t videoRate = 0;
1690 uint32_t fecRate = 0;
1691 uint32_t nackRate = 0;
1692 _rtpRtcp.BitrateSent(&sendBitrateKbit,
1693 &videoRate,
1694 &fecRate,
1695 &nackRate);
1696 sendBitrateKbit /= 1000;
1697 if(sendBitrateKbit != 0)
1698 {
1699 minIntervalMs = 360000/sendBitrateKbit;
1700 }
1701 }
1702 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1703 {
1704 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1705 }
1706 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1707 }
1708 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1709 }
1710
1711 // if the data does not fitt in the packet we fill it as much as possible
1712 int32_t buildVal = 0;
1713
1714 if(rtcpPacketTypeFlags & kRtcpSr)
1715 {
1716 if(hasReceived)
1717 {
1718 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
1719 } else
1720 {
1721 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac);
1722 }
1723 if(buildVal == -1)
1724 {
1725 return -1; // error
1726
1727 }else if(buildVal == -2)
1728 {
1729 break; // out of buffer
1730 }
1731 buildVal = BuildSDEC(rtcpbuffer, pos);
1732 if(buildVal == -1)
1733 {
1734 return -1; // error
1735
1736 }else if(buildVal == -2)
1737 {
1738 break; // out of buffer
1739 }
1740
1741 }else if(rtcpPacketTypeFlags & kRtcpRr)
1742 {
1743 if(hasReceived)
1744 {
1745 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
1746 }else
1747 {
1748 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
1749 }
1750 if(buildVal == -1)
1751 {
1752 return -1; // error
1753
1754 }else if(buildVal == -2)
1755 {
1756 break; // out of buffer
1757 }
1758 // only of set
1759 if(_CNAME[0] != 0)
1760 {
1761 buildVal = BuildSDEC(rtcpbuffer, pos);
1762 if(buildVal == -1)
1763 {
1764 return -1; // error
1765 }
1766 }
1767 }
1768 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1769 {
1770 // If present, this RTCP packet must be placed after a
1771 // receiver report.
1772 buildVal = BuildExtendedJitterReport(rtcpbuffer,
1773 pos,
1774 jitterTransmissionOffset);
1775 if(buildVal == -1)
1776 {
1777 return -1; // error
1778 }
1779 else if(buildVal == -2)
1780 {
1781 break; // out of buffer
1782 }
1783 }
1784 if(rtcpPacketTypeFlags & kRtcpPli)
1785 {
1786 buildVal = BuildPLI(rtcpbuffer, pos);
1787 if(buildVal == -1)
1788 {
1789 return -1; // error
1790
1791 }else if(buildVal == -2)
1792 {
1793 break; // out of buffer
1794 }
1795 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
1796 _pliCount++;
1797 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC, _pliCount);
1798 }
1799 if(rtcpPacketTypeFlags & kRtcpFir)
1800 {
1801 buildVal = BuildFIR(rtcpbuffer, pos, repeat);
1802 if(buildVal == -1)
1803 {
1804 return -1; // error
1805
1806 }else if(buildVal == -2)
1807 {
1808 break; // out of buffer
1809 }
1810 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
1811 _fullIntraRequestCount++;
1812 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
1813 _fullIntraRequestCount);
1814 }
1815 if(rtcpPacketTypeFlags & kRtcpSli)
1816 {
1817 buildVal = BuildSLI(rtcpbuffer, pos, (uint8_t)pictureID);
1818 if(buildVal == -1)
1819 {
1820 return -1; // error
1821
1822 }else if(buildVal == -2)
1823 {
1824 break; // out of buffer
1825 }
1826 }
1827 if(rtcpPacketTypeFlags & kRtcpRpsi)
1828 {
1829 const int8_t payloadType = _rtpRtcp.SendPayloadType();
1830 if(payloadType == -1)
1831 {
1832 return -1;
1833 }
1834 buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (uint8_t)payloadType);
1835 if(buildVal == -1)
1836 {
1837 return -1; // error
1838
1839 }else if(buildVal == -2)
1840 {
1841 break; // out of buffer
1842 }
1843 }
1844 if(rtcpPacketTypeFlags & kRtcpRemb)
1845 {
1846 buildVal = BuildREMB(rtcpbuffer, pos);
1847 if(buildVal == -1)
1848 {
1849 return -1; // error
1850
1851 }else if(buildVal == -2)
1852 {
1853 break; // out of buffer
1854 }
1855 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1856 }
1857 if(rtcpPacketTypeFlags & kRtcpBye)
1858 {
1859 buildVal = BuildBYE(rtcpbuffer, pos);
1860 if(buildVal == -1)
1861 {
1862 return -1; // error
1863
1864 }else if(buildVal == -2)
1865 {
1866 break; // out of buffer
1867 }
1868 }
1869 if(rtcpPacketTypeFlags & kRtcpApp)
1870 {
1871 buildVal = BuildAPP(rtcpbuffer, pos);
1872 if(buildVal == -1)
1873 {
1874 return -1; // error
1875
1876 }else if(buildVal == -2)
1877 {
1878 break; // out of buffer
1879 }
1880 }
1881 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1882 {
1883 buildVal = BuildTMMBR(rtcpbuffer, pos);
1884 if(buildVal == -1)
1885 {
1886 return -1; // error
1887
1888 }else if(buildVal == -2)
1889 {
1890 break; // out of buffer
1891 }
1892 }
1893 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1894 {
1895 buildVal = BuildTMMBN(rtcpbuffer, pos);
1896 if(buildVal == -1)
1897 {
1898 return -1; // error
1899
1900 }else if(buildVal == -2)
1901 {
1902 break; // out of buffer
1903 }
1904 }
1905 if(rtcpPacketTypeFlags & kRtcpNack)
1906 {
1907 std::string nackString;
1908 buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList,
1909 &nackString);
1910 if(buildVal == -1)
1911 {
1912 return -1; // error
1913
1914 }else if(buildVal == -2)
1915 {
1916 break; // out of buffer
1917 }
1918 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
1919 "nacks", TRACE_STR_COPY(nackString.c_str()));
1920 _nackCount++;
1921 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC, _nackCount);
1922 }
1923 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1924 {
1925 buildVal = BuildVoIPMetric(rtcpbuffer, pos);
1926 if(buildVal == -1)
1927 {
1928 return -1; // error
1929
1930 }else if(buildVal == -2)
1931 {
1932 break; // out of buffer
1933 }
1934 }
1935 }while (false);
1936 // Sanity don't send empty packets.
1937 if (pos == 0)
1938 {
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001939 return -1;
1940 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001941 return SendToNetwork(rtcpbuffer, (uint16_t)pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001942}
1943
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001944int32_t
1945RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
1946 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001947{
1948 CriticalSectionScoped lock(_criticalSectionTransport);
1949 if(_cbTransport)
1950 {
1951 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1952 {
1953 return 0;
1954 }
1955 }
1956 return -1;
1957}
1958
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001959int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00001960RTCPSender::SetCSRCStatus(const bool include)
1961{
1962 _includeCSRCs = include;
1963 return 0;
1964}
1965
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001966int32_t
1967RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
1968 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00001969{
1970 if(arrLength > kRtpCsrcSize)
1971 {
1972 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1973 assert(false);
1974 return -1;
1975 }
1976
1977 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1978
1979 for(int i = 0; i < arrLength;i++)
1980 {
1981 _CSRC[i] = arrOfCSRC[i];
1982 }
1983 _CSRCs = arrLength;
1984 return 0;
1985}
1986
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001987int32_t
1988RTCPSender::SetApplicationSpecificData(const uint8_t subType,
1989 const uint32_t name,
1990 const uint8_t* data,
1991 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001992{
1993 if(length %4 != 0)
1994 {
1995 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1996 return -1;
1997 }
1998 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1999
2000 if(_appData)
2001 {
2002 delete [] _appData;
2003 }
2004
2005 _appSend = true;
2006 _appSubType = subType;
2007 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002008 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002009 _appLength = length;
2010 memcpy(_appData, data, length);
2011 return 0;
2012}
2013
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002014int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002015RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2016{
2017 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2018 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2019
2020 _xrSendVoIPMetric = true;
2021 return 0;
2022}
2023
2024// called under critsect _criticalSectionRTCPSender
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002025int32_t RTCPSender::AddReportBlocks(uint8_t* rtcpbuffer,
2026 uint32_t& pos,
2027 uint8_t& numberOfReportBlocks,
2028 const RTCPReportBlock* received,
2029 const uint32_t NTPsec,
2030 const uint32_t NTPfrac) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002031 // sanity one block
2032 if(pos + 24 >= IP_PACKET_SIZE) {
2033 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2034 "%s invalid argument", __FUNCTION__);
2035 return -1;
2036 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002037 numberOfReportBlocks = _reportBlocks.size();
2038 if (received) {
2039 // add our multiple RR to numberOfReportBlocks
2040 numberOfReportBlocks++;
2041 }
2042 if (received) {
2043 // answer to the one that sends to me
2044 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
2045
2046 // Remote SSRC
2047 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
2048 pos += 4;
2049
2050 // fraction lost
2051 rtcpbuffer[pos++]=received->fractionLost;
2052
2053 // cumulative loss
2054 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2055 received->cumulativeLost);
2056 pos += 3;
2057 // extended highest seq_no, contain the highest sequence number received
2058 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2059 received->extendedHighSeqNum);
2060 pos += 4;
2061
2062 //Jitter
2063 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
2064 pos += 4;
2065
2066 // Last SR timestamp, our NTP time when we received the last report
2067 // This is the value that we read from the send report packet not when we
2068 // received it...
2069 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
2070 pos += 4;
2071
2072 // Delay since last received report,time since we received the report
2073 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2074 received->delaySinceLastSR);
2075 pos += 4;
2076 }
2077 if ((pos + _reportBlocks.size() * 24) >= IP_PACKET_SIZE) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002078 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2079 "%s invalid argument", __FUNCTION__);
2080 return -1;
2081 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002082 std::map<uint32_t, RTCPReportBlock*>::iterator it =
2083 _reportBlocks.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002084
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002085 for (; it != _reportBlocks.end(); it++) {
2086 // we can have multiple report block in a conference
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002087 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002088 RTCPReportBlock* reportBlock = it->second;
2089 if (reportBlock) {
2090 // Remote SSRC
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002091 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
2092 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002093
2094 // fraction lost
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002095 rtcpbuffer[pos++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002096
2097 // cumulative loss
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002098 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002099 reportBlock->cumulativeLost);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002100 pos += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002101
2102 // extended highest seq_no, contain the highest sequence number received
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002103 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002104 reportBlock->extendedHighSeqNum);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002105 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002106
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002107 //Jitter
2108 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002109 reportBlock->jitter);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002110 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002111
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002112 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002113 reportBlock->lastSR);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002114 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002115
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002116 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002117 reportBlock->delaySinceLastSR);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002118 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002119 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002120 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002121 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00002122}
2123
2124// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002125int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002126RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002127 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002128{
2129 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2130
2131 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2132 {
2133 _sendTMMBN = true;
2134 return 0;
2135 }
2136 return -1;
2137}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002138} // namespace webrtc