blob: ff9190d066709f085534042b114da541d63c54ad [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,
pwestin@webrtc.org741da942011-09-20 13:52:04 +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(),
92 _reportBlocks(),
93 _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
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000137 while (!_reportBlocks.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000138 std::map<uint32_t, RTCPReportBlock*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000139 _reportBlocks.begin();
140 delete it->second;
141 _reportBlocks.erase(it);
142 }
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 {
stefan@webrtc.org66b2e5c2013-07-05 14:30:48 +0000271 return SendRTCP(kRtcpBye, NULL);
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
stefan@webrtc.org66b2e5c2013-07-05 14:30:48 +0000376void RTCPSender::SetRemoteSSRC(uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000377{
378 CriticalSectionScoped lock(_criticalSectionRTCPSender);
379 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000380}
381
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000382int32_t
383RTCPSender::SetCameraDelay(const int32_t delayMS)
384{
385 CriticalSectionScoped lock(_criticalSectionRTCPSender);
386 if(delayMS > 1000 || delayMS < -1000)
387 {
388 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
389 return -1;
390 }
391 _cameraDelayMS = delayMS;
392 return 0;
393}
394
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000395int32_t RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000396 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000397 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000398 cName[RTCP_CNAME_SIZE - 1] = 0;
399 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000400 return 0;
401}
402
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000403int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000404 if (!cName)
405 return -1;
406
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000407 CriticalSectionScoped lock(_criticalSectionRTCPSender);
408 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
409 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
410 return 0;
411}
412
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000413int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
414 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000415 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000416 CriticalSectionScoped lock(_criticalSectionRTCPSender);
417 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
418 return -1;
419 }
420 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000421 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
422 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000423 _csrcCNAMEs[SSRC] = ptr;
424 return 0;
425}
426
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000427int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000428 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000429 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000430 _csrcCNAMEs.find(SSRC);
431
432 if (it == _csrcCNAMEs.end()) {
433 return -1;
434 }
435 delete it->second;
436 _csrcCNAMEs.erase(it);
437 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000438}
439
440bool
441RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
442{
443/*
444 For audio we use a fix 5 sec interval
445
446 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
447 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
448
449
450From RFC 3550
451
452 MAX RTCP BW is 5% if the session BW
453 A send report is approximately 65 bytes inc CNAME
454 A report report is approximately 28 bytes
455
456 The RECOMMENDED value for the reduced minimum in seconds is 360
457 divided by the session bandwidth in kilobits/second. This minimum
458 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
459
460 If the participant has not yet sent an RTCP packet (the variable
461 initial is true), the constant Tmin is set to 2.5 seconds, else it
462 is set to 5 seconds.
463
464 The interval between RTCP packets is varied randomly over the
465 range [0.5,1.5] times the calculated interval to avoid unintended
466 synchronization of all participants
467
468 if we send
469 If the participant is a sender (we_sent true), the constant C is
470 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
471 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
472 number of senders.
473
474 if we receive only
475 If we_sent is not true, the constant C is set
476 to the average RTCP packet size divided by 75% of the RTCP
477 bandwidth. The constant n is set to the number of receivers
478 (members - senders). If the number of senders is greater than
479 25%, senders and receivers are treated together.
480
481 reconsideration NOT required for peer-to-peer
482 "timer reconsideration" is
483 employed. This algorithm implements a simple back-off mechanism
484 which causes users to hold back RTCP packet transmission if the
485 group sizes are increasing.
486
487 n = number of members
488 C = avg_size/(rtcpBW/4)
489
490 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
491
492 4. The calculated interval T is set to a number uniformly distributed
493 between 0.5 and 1.5 times the deterministic calculated interval.
494
495 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
496 for the fact that the timer reconsideration algorithm converges to
497 a value of the RTCP bandwidth below the intended average
498*/
499
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000500 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000501
502 CriticalSectionScoped lock(_criticalSectionRTCPSender);
503
niklase@google.com470e71d2011-07-07 08:21:25 +0000504 if(_method == kRtcpOff)
505 {
506 return false;
507 }
508
niklase@google.com470e71d2011-07-07 08:21:25 +0000509 if(!_audio && sendKeyframeBeforeRTP)
510 {
511 // for video key-frames we want to send the RTCP before the large key-frame
512 // if we have a 100 ms margin
513 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
514 }
515
516 if(now > _nextTimeToSendRTCP)
517 {
518 return true;
519
520 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
521 {
522 // wrap
523 return true;
524 }
525 return false;
526}
527
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000528uint32_t
529RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000530{
531 CriticalSectionScoped lock(_criticalSectionRTCPSender);
532
533 lastRTCPTime = _lastRTCPTime[0];
534 return _lastSendReport[0];
535}
536
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000537uint32_t
538RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000539{
540 CriticalSectionScoped lock(_criticalSectionRTCPSender);
541
542 // This is only saved when we are the sender
543 if((_lastSendReport[0] == 0) || (sendReport == 0))
544 {
545 return 0; // will be ignored
546 } else
547 {
548 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
549 {
550 if( _lastSendReport[i] == sendReport)
551 {
552 return _lastRTCPTime[i];
553 }
554 }
555 }
556 return 0;
557}
558
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000559int32_t RTCPSender::AddReportBlock(const uint32_t SSRC,
560 const RTCPReportBlock* reportBlock) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000561 if (reportBlock == NULL) {
562 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
563 "%s invalid argument", __FUNCTION__);
564 return -1;
565 }
566 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000567
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000568 if (_reportBlocks.size() >= RTCP_MAX_REPORT_BLOCKS) {
569 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
570 "%s invalid argument", __FUNCTION__);
571 return -1;
572 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000573 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000574 _reportBlocks.find(SSRC);
575 if (it != _reportBlocks.end()) {
576 delete it->second;
577 _reportBlocks.erase(it);
578 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000579 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
580 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
581 _reportBlocks[SSRC] = copyReportBlock;
582 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000583}
584
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000585int32_t RTCPSender::RemoveReportBlock(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000586 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000587
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000588 std::map<uint32_t, RTCPReportBlock*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000589 _reportBlocks.find(SSRC);
590
591 if (it == _reportBlocks.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000592 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000593 }
594 delete it->second;
595 _reportBlocks.erase(it);
596 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000597}
598
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000599int32_t
600RTCPSender::BuildSR(uint8_t* rtcpbuffer,
601 uint32_t& pos,
602 const uint32_t NTPsec,
603 const uint32_t NTPfrac,
niklase@google.com470e71d2011-07-07 08:21:25 +0000604 const RTCPReportBlock* received)
605{
606 // sanity
607 if(pos + 52 >= IP_PACKET_SIZE)
608 {
609 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
610 return -2;
611 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000612 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000613
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000614 uint32_t posNumberOfReportBlocks = pos;
615 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000616
617 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000618 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000619
620 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
621 {
622 // shift old
623 _lastSendReport[i+1] = _lastSendReport[i];
624 _lastRTCPTime[i+1] =_lastRTCPTime[i];
625 }
626
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000627 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000628 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000629
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000630 uint32_t freqHz = 90000; // For video
631 if(_audio) {
632 freqHz = _rtpRtcp.CurrentSendFrequencyHz();
niklase@google.com470e71d2011-07-07 08:21:25 +0000633 }
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000634
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000635 // The timestamp of this RTCP packet should be estimated as the timestamp of
636 // the frame being captured at this moment. We are calculating that
637 // timestamp as the last frame's timestamp + the time since the last frame
638 // was captured.
639 {
640 // Needs protection since this method is called on the process thread.
641 CriticalSectionScoped lock(_criticalSectionRTCPSender);
642 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
643 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
644 (freqHz / 1000);
645 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000646
647 // Add sender data
648 // Save for our length field
649 pos++;
650 pos++;
651
652 // Add our own SSRC
653 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
654 pos += 4;
655 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000656 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000657 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000658 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000659 pos += 4;
660 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
661 pos += 4;
662
663 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000664 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000665 pos += 4;
666
667 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000668 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000669 pos += 4;
670
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000671 uint8_t numberOfReportBlocks = 0;
672 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000673 if(retVal < 0)
674 {
675 //
676 return retVal ;
677 }
678 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
679
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000680 uint16_t len = uint16_t((pos/4) -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000681 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
682 return 0;
683}
684
685
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000686int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer,
687 uint32_t& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000688 size_t lengthCname = strlen(_CNAME);
689 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000690
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000691 // sanity
692 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
693 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
694 "%s invalid argument", __FUNCTION__);
695 return -2;
696 }
697 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000698
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000699 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000700 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
701 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000702
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000703 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000704 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000705 pos++;
706 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000707
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000708 // Add our own SSRC
709 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
710 pos += 4;
711
712 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000713 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000714
715 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000716 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000717
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000718 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000719
720 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
721 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000722 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000723
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000724 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000725 // We must have a zero field even if we have an even multiple of 4 bytes
726 if ((pos % 4) == 0) {
727 padding++;
728 rtcpbuffer[pos++]=0;
729 }
730 while ((pos % 4) != 0) {
731 padding++;
732 rtcpbuffer[pos++]=0;
733 }
734 SDESLength += padding;
735
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000736 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000737 _csrcCNAMEs.begin();
738
739 for(; it != _csrcCNAMEs.end(); it++) {
740 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000741 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000742
743 // Add SSRC
744 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000745 pos += 4;
746
747 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000748 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000749
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000750 size_t length = strlen(cname->name);
751 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000752
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000753 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000754 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000755
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000756 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000757
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000758 pos += length;
759 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000760 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000761
762 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000763 if((pos % 4) == 0){
764 padding++;
765 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000766 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000767 while((pos % 4) != 0){
768 padding++;
769 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000770 }
771 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000772 }
773 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000774 uint16_t buffer_length = (SDESLength / 4) - 1;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000775 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
776 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000777 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000778}
779
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000780int32_t
781RTCPSender::BuildRR(uint8_t* rtcpbuffer,
782 uint32_t& pos,
783 const uint32_t NTPsec,
784 const uint32_t NTPfrac,
niklase@google.com470e71d2011-07-07 08:21:25 +0000785 const RTCPReportBlock* received)
786{
787 // sanity one block
788 if(pos + 32 >= IP_PACKET_SIZE)
789 {
790 return -2;
791 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000792 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000793
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000794 rtcpbuffer[pos++]=(uint8_t)0x80;
795 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000796
797 // Save for our length field
798 pos++;
799 pos++;
800
801 // Add our own SSRC
802 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
803 pos += 4;
804
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000805 uint8_t numberOfReportBlocks = 0;
806 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000807 if(retVal < 0)
808 {
809 return retVal;
810 }
811 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
812
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000813 uint16_t len = uint16_t((pos)/4 -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000814 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
815 return 0;
816}
817
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000818// From RFC 5450: Transmission Time Offsets in RTP Streams.
819// 0 1 2 3
820// 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
821// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
822// hdr |V=2|P| RC | PT=IJ=195 | length |
823// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
824// | inter-arrival jitter |
825// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
826// . .
827// . .
828// . .
829// | inter-arrival jitter |
830// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
831//
832// If present, this RTCP packet must be placed after a receiver report
833// (inside a compound RTCP packet), and MUST have the same value for RC
834// (reception report count) as the receiver report.
835
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000836int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000837RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000838 uint8_t* rtcpbuffer,
839 uint32_t& pos,
840 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000841{
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000842 if (_reportBlocks.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000843 {
844 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
845 return 0;
846 }
847
848 // sanity
849 if(pos + 8 >= IP_PACKET_SIZE)
850 {
851 return -2;
852 }
853 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000854 uint8_t RC = 1;
855 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
856 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000857
858 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000859 rtcpbuffer[pos++]=(uint8_t)0;
860 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000861
862 // Add inter-arrival jitter
863 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
864 jitterTransmissionTimeOffset);
865 pos += 4;
866 return 0;
867}
868
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000869int32_t
870RTCPSender::BuildPLI(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000871{
872 // sanity
873 if(pos + 12 >= IP_PACKET_SIZE)
874 {
875 return -2;
876 }
877 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000878 uint8_t FMT = 1;
879 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
880 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000881
882 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000883 rtcpbuffer[pos++]=(uint8_t)0;
884 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000885
886 // Add our own SSRC
887 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
888 pos += 4;
889
890 // Add the remote SSRC
891 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
892 pos += 4;
893 return 0;
894}
895
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000896int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
897 uint32_t& pos,
898 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000899 // sanity
900 if(pos + 20 >= IP_PACKET_SIZE) {
901 return -2;
902 }
903 if (!repeat) {
904 _sequenceNumberFIR++; // do not increase if repetition
905 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000906
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000907 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000908 uint8_t FMT = 4;
909 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
910 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000911
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000912 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000913 rtcpbuffer[pos++] = (uint8_t)0;
914 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000915
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000916 // Add our own SSRC
917 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
918 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000919
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000920 // RFC 5104 4.3.1.2. Semantics
921 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000922 rtcpbuffer[pos++] = (uint8_t)0;
923 rtcpbuffer[pos++] = (uint8_t)0;
924 rtcpbuffer[pos++] = (uint8_t)0;
925 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000926
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000927 // Additional Feedback Control Information (FCI)
928 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
929 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000930
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000931 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
932 rtcpbuffer[pos++] = (uint8_t)0;
933 rtcpbuffer[pos++] = (uint8_t)0;
934 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000935 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000936}
937
938/*
939 0 1 2 3
940 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
941 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
942 | First | Number | PictureID |
943 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
944*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000945int32_t
946RTCPSender::BuildSLI(uint8_t* rtcpbuffer, uint32_t& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000947{
948 // sanity
949 if(pos + 16 >= IP_PACKET_SIZE)
950 {
951 return -2;
952 }
953 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000954 uint8_t FMT = 2;
955 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
956 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000957
958 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000959 rtcpbuffer[pos++]=(uint8_t)0;
960 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000961
962 // Add our own SSRC
963 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
964 pos += 4;
965
966 // Add the remote SSRC
967 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
968 pos += 4;
969
970 // Add first, number & picture ID 6 bits
971 // first = 0, 13 - bits
972 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000973 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000974 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
975 pos += 4;
976 return 0;
977}
978
979/*
980 0 1 2 3
981 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
982 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
983 | PB |0| Payload Type| Native RPSI bit string |
984 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
985 | defined per codec ... | Padding (0) |
986 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
987*/
988/*
989* Note: not generic made for VP8
990*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000991int32_t
992RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
993 uint32_t& pos,
994 const uint64_t pictureID,
995 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +0000996{
997 // sanity
998 if(pos + 24 >= IP_PACKET_SIZE)
999 {
1000 return -2;
1001 }
1002 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001003 uint8_t FMT = 3;
1004 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1005 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001006
1007 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001008 uint32_t bitsRequired = 7;
1009 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001010 while((pictureID>>bitsRequired) > 0)
1011 {
1012 bitsRequired += 7;
1013 bytesRequired++;
1014 }
1015
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001016 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001017 if(bytesRequired > 6)
1018 {
1019 size = 5;
1020 } else if(bytesRequired > 2)
1021 {
1022 size = 4;
1023 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001024 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001025 rtcpbuffer[pos++]=size;
1026
1027 // Add our own SSRC
1028 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1029 pos += 4;
1030
1031 // Add the remote SSRC
1032 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1033 pos += 4;
1034
1035 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001036 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001037 if(paddingBytes == 4)
1038 {
1039 paddingBytes = 0;
1040 }
1041 // add padding length in bits
1042 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1043 pos++;
1044
1045 // add payload type
1046 rtcpbuffer[pos] = payloadType;
1047 pos++;
1048
1049 // add picture ID
1050 for(int i = bytesRequired-1; i > 0; i--)
1051 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001052 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001053 pos++;
1054 }
1055 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001056 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001057 pos++;
1058
1059 // add padding
1060 for(int j = 0; j <paddingBytes; j++)
1061 {
1062 rtcpbuffer[pos] = 0;
1063 pos++;
1064 }
1065 return 0;
1066}
1067
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001068int32_t
1069RTCPSender::BuildREMB(uint8_t* rtcpbuffer, uint32_t& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001070{
1071 // sanity
1072 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1073 {
1074 return -2;
1075 }
1076 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001077 uint8_t FMT = 15;
1078 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1079 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001080
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001081 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001082 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1083
1084 // Add our own SSRC
1085 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1086 pos += 4;
1087
1088 // Remote SSRC must be 0
1089 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1090 pos += 4;
1091
1092 rtcpbuffer[pos++]='R';
1093 rtcpbuffer[pos++]='E';
1094 rtcpbuffer[pos++]='M';
1095 rtcpbuffer[pos++]='B';
1096
1097 rtcpbuffer[pos++] = _lengthRembSSRC;
1098 // 6 bit Exp
1099 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001100 uint8_t brExp = 0;
1101 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001102 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001103 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001104 {
1105 brExp = i;
1106 break;
1107 }
1108 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001109 const uint32_t brMantissa = (_rembBitrate >> brExp);
1110 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1111 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1112 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001113
1114 for (int i = 0; i < _lengthRembSSRC; i++)
1115 {
1116 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1117 pos += 4;
1118 }
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001119 TRACE_COUNTER_ID1("webrtc_rtp", "RTCPRembBitrate", _SSRC, _rembBitrate);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001120 return 0;
1121}
1122
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001123void
1124RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001125{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001126 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001127 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001128}
1129
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001130int32_t
1131RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001132{
1133 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1134 // If the sender is an owner of the TMMBN -> send TMMBR
1135 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1136
niklase@google.com470e71d2011-07-07 08:21:25 +00001137 // get current bounding set from RTCP receiver
1138 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001139 // store in candidateSet, allocates one extra slot
1140 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001141
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001142 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1143 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1144 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001145 int32_t lengthOfBoundingSet
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001146 = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001147
1148 if(lengthOfBoundingSet > 0)
1149 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001150 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001151 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001152 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1153 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001154 {
1155 // do not send the same tuple
1156 return 0;
1157 }
1158 }
1159 if(!tmmbrOwner)
1160 {
1161 // use received bounding set as candidate set
1162 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001163 candidateSet->SetEntry(lengthOfBoundingSet,
1164 _tmmbr_Send,
1165 _packetOH_Send,
1166 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001167 int numCandidates = lengthOfBoundingSet+ 1;
1168
1169 // find bounding set
1170 TMMBRSet* boundingSet = NULL;
1171 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1172 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1173 {
1174 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1175 }
1176 if(!tmmbrOwner)
1177 {
1178 // did not enter bounding set, no meaning to send this request
1179 return 0;
1180 }
1181 }
1182 }
1183
1184 if(_tmmbr_Send)
1185 {
1186 // sanity
1187 if(pos + 20 >= IP_PACKET_SIZE)
1188 {
1189 return -2;
1190 }
1191 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001192 uint8_t FMT = 3;
1193 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1194 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001195
1196 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001197 rtcpbuffer[pos++]=(uint8_t)0;
1198 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001199
1200 // Add our own SSRC
1201 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1202 pos += 4;
1203
1204 // RFC 5104 4.2.1.2. Semantics
1205
1206 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001207 rtcpbuffer[pos++]=(uint8_t)0;
1208 rtcpbuffer[pos++]=(uint8_t)0;
1209 rtcpbuffer[pos++]=(uint8_t)0;
1210 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001211
1212 // Additional Feedback Control Information (FCI)
1213 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1214 pos += 4;
1215
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001216 uint32_t bitRate = _tmmbr_Send*1000;
1217 uint32_t mmbrExp = 0;
1218 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001219 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001220 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001221 {
1222 mmbrExp = i;
1223 break;
1224 }
1225 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001226 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001227
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001228 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1229 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1230 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1231 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001232 }
1233 return 0;
1234}
1235
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001236int32_t
1237RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001238{
1239 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1240 if(boundingSet == NULL)
1241 {
1242 return -1;
1243 }
1244 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001245 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001246 {
1247 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1248 return -2;
1249 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001250 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001251 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001252 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1253 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001254
1255 //Add length later
1256 int posLength = pos;
1257 pos++;
1258 pos++;
1259
1260 // Add our own SSRC
1261 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1262 pos += 4;
1263
1264 // RFC 5104 4.2.2.2. Semantics
1265
1266 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001267 rtcpbuffer[pos++]=(uint8_t)0;
1268 rtcpbuffer[pos++]=(uint8_t)0;
1269 rtcpbuffer[pos++]=(uint8_t)0;
1270 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001271
1272 // Additional Feedback Control Information (FCI)
1273 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001274 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001275 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001276 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001277 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001278 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001279 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1280 pos += 4;
1281
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001282 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1283 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001284 for(int i=0; i<64; i++)
1285 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001286 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001287 {
1288 mmbrExp = i;
1289 break;
1290 }
1291 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001292 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1293 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001294
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001295 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1296 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1297 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1298 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001299 numBoundingSet++;
1300 }
1301 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001302 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1303 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1304 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001305 return 0;
1306}
1307
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001308int32_t
1309RTCPSender::BuildAPP(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001310{
1311 // sanity
1312 if(_appData == NULL)
1313 {
1314 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1315 return -1;
1316 }
1317 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1318 {
1319 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1320 return -2;
1321 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001322 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001323
1324 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001325 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001326
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001327 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1328 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1329 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001330
1331 // Add our own SSRC
1332 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1333 pos += 4;
1334
1335 // Add our application name
1336 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1337 pos += 4;
1338
1339 // Add the data
1340 memcpy(rtcpbuffer +pos, _appData,_appLength);
1341 pos += _appLength;
1342 return 0;
1343}
1344
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001345int32_t
1346RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
1347 uint32_t& pos,
1348 const int32_t nackSize,
1349 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001350 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001351{
1352 // sanity
1353 if(pos + 16 >= IP_PACKET_SIZE)
1354 {
1355 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1356 return -2;
1357 }
1358
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001359 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001360 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001361 uint8_t FMT = 1;
1362 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1363 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001364
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001365 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001366 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001367 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001368
1369 // Add our own SSRC
1370 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1371 pos += 4;
1372
1373 // Add the remote SSRC
1374 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1375 pos += 4;
1376
edjee@google.com79b02892013-04-04 19:43:34 +00001377 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001378 // Build NACK bitmasks and write them to the RTCP message.
1379 // The nack list should be sorted and not contain duplicates if one
1380 // wants to build the smallest rtcp nack packet.
1381 int numOfNackFields = 0;
1382 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1383 (IP_PACKET_SIZE - pos) / 4);
1384 int i = 0;
1385 while (i < nackSize && numOfNackFields < maxNackFields) {
1386 stringBuilder.PushNACK(nackList[i]);
1387 uint16_t nack = nackList[i++];
1388 uint16_t bitmask = 0;
1389 while (i < nackSize) {
1390 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1391 if (shift >= 0 && shift <= 15) {
1392 stringBuilder.PushNACK(nackList[i]);
1393 bitmask |= (1 << shift);
1394 ++i;
1395 } else {
1396 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001397 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001398 }
1399 // Write the sequence number and the bitmask to the packet.
1400 assert(pos + 4 < IP_PACKET_SIZE);
1401 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
1402 pos += 2;
1403 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
1404 pos += 2;
1405 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001406 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001407 if (i != nackSize) {
1408 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1409 "Nack list to large for one packet.");
1410 }
1411 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001412 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001413 return 0;
1414}
1415
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001416int32_t
1417RTCPSender::BuildBYE(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001418{
1419 // sanity
1420 if(pos + 8 >= IP_PACKET_SIZE)
1421 {
1422 return -2;
1423 }
1424 if(_includeCSRCs)
1425 {
1426 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001427 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1428 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001429
1430 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001431 rtcpbuffer[pos++]=(uint8_t)0;
1432 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001433
1434 // Add our own SSRC
1435 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1436 pos += 4;
1437
1438 // add CSRCs
1439 for(int i = 0; i < _CSRCs; i++)
1440 {
1441 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1442 pos += 4;
1443 }
1444 } else
1445 {
1446 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001447 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1448 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001449
1450 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001451 rtcpbuffer[pos++]=(uint8_t)0;
1452 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001453
1454 // Add our own SSRC
1455 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1456 pos += 4;
1457 }
1458 return 0;
1459}
1460
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001461int32_t
1462RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001463{
1464 // sanity
1465 if(pos + 44 >= IP_PACKET_SIZE)
1466 {
1467 return -2;
1468 }
1469
1470 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001471 rtcpbuffer[pos++]=(uint8_t)0x80;
1472 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001473
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001474 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001475
1476 // handle length later on
1477 pos++;
1478 pos++;
1479
1480 // Add our own SSRC
1481 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1482 pos += 4;
1483
1484 // Add a VoIP metrics block
1485 rtcpbuffer[pos++]=7;
1486 rtcpbuffer[pos++]=0;
1487 rtcpbuffer[pos++]=0;
1488 rtcpbuffer[pos++]=8;
1489
1490 // Add the remote SSRC
1491 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1492 pos += 4;
1493
1494 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1495 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1496 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1497 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1498
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001499 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1500 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1501 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1502 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001503
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001504 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1505 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1506 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1507 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001508
1509 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1510 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1511 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1512 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1513
1514 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1515 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1516 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1517 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1518
1519 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1520 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001521 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1522 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001523
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001524 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1525 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1526 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1527 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001528
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001529 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1530 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001531 return 0;
1532}
1533
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001534int32_t
stefan@webrtc.org66b2e5c2013-07-05 14:30:48 +00001535RTCPSender::SendRTCP(
1536 uint32_t packetTypeFlags,
1537 const ReceiveStatistics::RtpReceiveStatistics* receive_stats,
1538 int32_t nackSize,
1539 const uint16_t* nackList,
1540 bool repeat,
1541 uint64_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +00001542{
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001543 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1544 uint32_t pos = 0;
1545 uint8_t rtcpbuffer[IP_PACKET_SIZE];
niklase@google.com470e71d2011-07-07 08:21:25 +00001546
niklase@google.com470e71d2011-07-07 08:21:25 +00001547 do // only to be able to use break :) (and the critsect must be inside its own scope)
1548 {
1549 // collect the received information
1550 RTCPReportBlock received;
1551 bool hasReceived = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001552 uint32_t NTPsec = 0;
1553 uint32_t NTPfrac = 0;
xians@webrtc.org8738d272011-11-25 13:43:53 +00001554 bool rtcpCompound = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001555 uint32_t jitterTransmissionOffset = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001556
xians@webrtc.org8738d272011-11-25 13:43:53 +00001557 {
1558 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1559 if(_method == kRtcpOff)
1560 {
1561 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1562 "%s invalid state", __FUNCTION__);
1563 return -1;
1564 }
1565 rtcpCompound = (_method == kRtcpCompound) ? true : false;
1566 }
1567
1568 if (rtcpCompound ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001569 rtcpPacketTypeFlags & kRtcpReport ||
1570 rtcpPacketTypeFlags & kRtcpSr ||
1571 rtcpPacketTypeFlags & kRtcpRr)
1572 {
stefan@webrtc.org66b2e5c2013-07-05 14:30:48 +00001573 // Do we have receive statistics to send?
1574 if (receive_stats)
niklase@google.com470e71d2011-07-07 08:21:25 +00001575 {
stefan@webrtc.org66b2e5c2013-07-05 14:30:48 +00001576 received.fractionLost = receive_stats->fraction_lost;
1577 received.cumulativeLost = receive_stats->cumulative_lost;
1578 received.extendedHighSeqNum =
1579 receive_stats->extended_max_sequence_number;
1580 received.jitter = receive_stats->jitter;
1581 jitterTransmissionOffset = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001582 hasReceived = true;
1583
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001584 uint32_t lastReceivedRRNTPsecs = 0;
1585 uint32_t lastReceivedRRNTPfrac = 0;
1586 uint32_t remoteSR = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001587
1588 // ok even if we have not received a SR, we will send 0 in that case
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001589 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1590 lastReceivedRRNTPfrac,
1591 remoteSR);
niklase@google.com470e71d2011-07-07 08:21:25 +00001592
1593 // get our NTP as late as possible to avoid a race
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001594 _clock->CurrentNtp(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001595
1596 // Delay since last received report
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001597 uint32_t delaySinceLastReceivedSR = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001598 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
1599 {
1600 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001601 uint32_t now=NTPsec&0x0000FFFF;
niklase@google.com470e71d2011-07-07 08:21:25 +00001602 now <<=16;
1603 now += (NTPfrac&0xffff0000)>>16;
1604
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001605 uint32_t receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
niklase@google.com470e71d2011-07-07 08:21:25 +00001606 receiveTime <<=16;
1607 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1608
1609 delaySinceLastReceivedSR = now-receiveTime;
1610 }
1611 received.delaySinceLastSR = delaySinceLastReceivedSR;
1612 received.lastSR = remoteSR;
1613 } else
1614 {
1615 // we need to send our NTP even if we dont have received any reports
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001616 _clock->CurrentNtp(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001617 }
1618 }
1619
1620 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1621
1622 if(_TMMBR ) // attach TMMBR to send and receive reports
1623 {
1624 rtcpPacketTypeFlags |= kRtcpTmmbr;
1625 }
1626 if(_appSend)
1627 {
1628 rtcpPacketTypeFlags |= kRtcpApp;
1629 _appSend = false;
1630 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001631 if(_REMB && _sendREMB)
1632 {
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +00001633 // Always attach REMB to SR if that is configured. Note that REMB is
1634 // only sent on one of the RTP modules in the REMB group.
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001635 rtcpPacketTypeFlags |= kRtcpRemb;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001636 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001637 if(_xrSendVoIPMetric)
1638 {
1639 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1640 _xrSendVoIPMetric = false;
1641 }
1642 if(_sendTMMBN) // set when having received a TMMBR
1643 {
1644 rtcpPacketTypeFlags |= kRtcpTmmbn;
1645 _sendTMMBN = false;
1646 }
1647
1648 if(_method == kRtcpCompound)
1649 {
1650 if(_sending)
1651 {
1652 rtcpPacketTypeFlags |= kRtcpSr;
1653 } else
1654 {
1655 rtcpPacketTypeFlags |= kRtcpRr;
1656 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001657 if (_IJ && hasReceived)
1658 {
1659 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1660 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001661 } else if(_method == kRtcpNonCompound)
1662 {
1663 if(rtcpPacketTypeFlags & kRtcpReport)
1664 {
1665 if(_sending)
1666 {
1667 rtcpPacketTypeFlags |= kRtcpSr;
1668 } else
1669 {
1670 rtcpPacketTypeFlags |= kRtcpRr;
1671 }
1672 }
1673 }
1674 if( rtcpPacketTypeFlags & kRtcpRr ||
1675 rtcpPacketTypeFlags & kRtcpSr)
1676 {
1677 // generate next time to send a RTCP report
1678 // seeded from RTP constructor
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001679 int32_t random = rand() % 1000;
1680 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
niklase@google.com470e71d2011-07-07 08:21:25 +00001681
1682 if(_audio)
1683 {
1684 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
1685 }else
1686 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001687 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
niklase@google.com470e71d2011-07-07 08:21:25 +00001688 if(_sending)
1689 {
1690 // calc bw for video 360/sendBW in kbit/s
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001691 uint32_t sendBitrateKbit = 0;
1692 uint32_t videoRate = 0;
1693 uint32_t fecRate = 0;
1694 uint32_t nackRate = 0;
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001695 _rtpRtcp.BitrateSent(&sendBitrateKbit,
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001696 &videoRate,
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001697 &fecRate,
1698 &nackRate);
1699 sendBitrateKbit /= 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001700 if(sendBitrateKbit != 0)
1701 {
1702 minIntervalMs = 360000/sendBitrateKbit;
1703 }
1704 }
1705 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1706 {
1707 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1708 }
1709 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1710 }
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001711 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
niklase@google.com470e71d2011-07-07 08:21:25 +00001712 }
1713
1714 // if the data does not fitt in the packet we fill it as much as possible
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001715 int32_t buildVal = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001716
1717 if(rtcpPacketTypeFlags & kRtcpSr)
1718 {
1719 if(hasReceived)
1720 {
1721 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
1722 } else
1723 {
1724 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac);
1725 }
1726 if(buildVal == -1)
1727 {
1728 return -1; // error
1729
1730 }else if(buildVal == -2)
1731 {
1732 break; // out of buffer
1733 }
1734 buildVal = BuildSDEC(rtcpbuffer, pos);
1735 if(buildVal == -1)
1736 {
1737 return -1; // error
1738
1739 }else if(buildVal == -2)
1740 {
1741 break; // out of buffer
1742 }
1743
1744 }else if(rtcpPacketTypeFlags & kRtcpRr)
1745 {
1746 if(hasReceived)
1747 {
1748 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
1749 }else
1750 {
1751 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
1752 }
1753 if(buildVal == -1)
1754 {
1755 return -1; // error
1756
1757 }else if(buildVal == -2)
1758 {
1759 break; // out of buffer
1760 }
1761 // only of set
1762 if(_CNAME[0] != 0)
1763 {
1764 buildVal = BuildSDEC(rtcpbuffer, pos);
1765 if(buildVal == -1)
1766 {
1767 return -1; // error
1768 }
1769 }
1770 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001771 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1772 {
1773 // If present, this RTCP packet must be placed after a
1774 // receiver report.
1775 buildVal = BuildExtendedJitterReport(rtcpbuffer,
1776 pos,
1777 jitterTransmissionOffset);
1778 if(buildVal == -1)
1779 {
1780 return -1; // error
1781 }
1782 else if(buildVal == -2)
1783 {
1784 break; // out of buffer
1785 }
1786 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001787 if(rtcpPacketTypeFlags & kRtcpPli)
1788 {
1789 buildVal = BuildPLI(rtcpbuffer, pos);
1790 if(buildVal == -1)
1791 {
1792 return -1; // error
1793
1794 }else if(buildVal == -2)
1795 {
1796 break; // out of buffer
1797 }
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001798 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
edjee@google.com79b02892013-04-04 19:43:34 +00001799 _pliCount++;
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001800 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC, _pliCount);
niklase@google.com470e71d2011-07-07 08:21:25 +00001801 }
1802 if(rtcpPacketTypeFlags & kRtcpFir)
1803 {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001804 buildVal = BuildFIR(rtcpbuffer, pos, repeat);
niklase@google.com470e71d2011-07-07 08:21:25 +00001805 if(buildVal == -1)
1806 {
1807 return -1; // error
1808
1809 }else if(buildVal == -2)
1810 {
1811 break; // out of buffer
1812 }
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001813 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
edjee@google.com79b02892013-04-04 19:43:34 +00001814 _fullIntraRequestCount++;
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001815 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
1816 _fullIntraRequestCount);
niklase@google.com470e71d2011-07-07 08:21:25 +00001817 }
1818 if(rtcpPacketTypeFlags & kRtcpSli)
1819 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001820 buildVal = BuildSLI(rtcpbuffer, pos, (uint8_t)pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +00001821 if(buildVal == -1)
1822 {
1823 return -1; // error
1824
1825 }else if(buildVal == -2)
1826 {
1827 break; // out of buffer
1828 }
1829 }
1830 if(rtcpPacketTypeFlags & kRtcpRpsi)
1831 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001832 const int8_t payloadType = _rtpRtcp.SendPayloadType();
niklase@google.com470e71d2011-07-07 08:21:25 +00001833 if(payloadType == -1)
1834 {
1835 return -1;
1836 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001837 buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (uint8_t)payloadType);
niklase@google.com470e71d2011-07-07 08:21:25 +00001838 if(buildVal == -1)
1839 {
1840 return -1; // error
1841
1842 }else if(buildVal == -2)
1843 {
1844 break; // out of buffer
1845 }
1846 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001847 if(rtcpPacketTypeFlags & kRtcpRemb)
1848 {
1849 buildVal = BuildREMB(rtcpbuffer, pos);
1850 if(buildVal == -1)
1851 {
1852 return -1; // error
1853
1854 }else if(buildVal == -2)
1855 {
1856 break; // out of buffer
1857 }
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001858 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001859 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001860 if(rtcpPacketTypeFlags & kRtcpBye)
1861 {
1862 buildVal = BuildBYE(rtcpbuffer, pos);
1863 if(buildVal == -1)
1864 {
1865 return -1; // error
1866
1867 }else if(buildVal == -2)
1868 {
1869 break; // out of buffer
1870 }
1871 }
1872 if(rtcpPacketTypeFlags & kRtcpApp)
1873 {
1874 buildVal = BuildAPP(rtcpbuffer, pos);
1875 if(buildVal == -1)
1876 {
1877 return -1; // error
1878
1879 }else if(buildVal == -2)
1880 {
1881 break; // out of buffer
1882 }
1883 }
1884 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1885 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001886 buildVal = BuildTMMBR(rtcpbuffer, pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001887 if(buildVal == -1)
1888 {
1889 return -1; // error
1890
1891 }else if(buildVal == -2)
1892 {
1893 break; // out of buffer
1894 }
1895 }
1896 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1897 {
1898 buildVal = BuildTMMBN(rtcpbuffer, pos);
1899 if(buildVal == -1)
1900 {
1901 return -1; // error
1902
1903 }else if(buildVal == -2)
1904 {
1905 break; // out of buffer
1906 }
1907 }
1908 if(rtcpPacketTypeFlags & kRtcpNack)
1909 {
edjee@google.com79b02892013-04-04 19:43:34 +00001910 std::string nackString;
1911 buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList,
1912 &nackString);
niklase@google.com470e71d2011-07-07 08:21:25 +00001913 if(buildVal == -1)
1914 {
1915 return -1; // error
1916
1917 }else if(buildVal == -2)
1918 {
1919 break; // out of buffer
1920 }
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001921 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
1922 "nacks", TRACE_STR_COPY(nackString.c_str()));
edjee@google.com79b02892013-04-04 19:43:34 +00001923 _nackCount++;
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001924 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC, _nackCount);
niklase@google.com470e71d2011-07-07 08:21:25 +00001925 }
1926 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1927 {
1928 buildVal = BuildVoIPMetric(rtcpbuffer, pos);
1929 if(buildVal == -1)
1930 {
1931 return -1; // error
1932
1933 }else if(buildVal == -2)
1934 {
1935 break; // out of buffer
1936 }
1937 }
1938 }while (false);
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001939 // Sanity don't send empty packets.
1940 if (pos == 0)
1941 {
1942 return -1;
1943 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001944 return SendToNetwork(rtcpbuffer, (uint16_t)pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001945}
1946
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001947int32_t
1948RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
1949 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001950{
1951 CriticalSectionScoped lock(_criticalSectionTransport);
1952 if(_cbTransport)
1953 {
1954 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1955 {
1956 return 0;
1957 }
1958 }
1959 return -1;
1960}
1961
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001962int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00001963RTCPSender::SetCSRCStatus(const bool include)
1964{
1965 _includeCSRCs = include;
1966 return 0;
1967}
1968
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001969int32_t
1970RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
1971 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00001972{
1973 if(arrLength > kRtpCsrcSize)
1974 {
1975 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1976 assert(false);
1977 return -1;
1978 }
1979
1980 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1981
1982 for(int i = 0; i < arrLength;i++)
1983 {
1984 _CSRC[i] = arrOfCSRC[i];
1985 }
1986 _CSRCs = arrLength;
1987 return 0;
1988}
1989
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001990int32_t
1991RTCPSender::SetApplicationSpecificData(const uint8_t subType,
1992 const uint32_t name,
1993 const uint8_t* data,
1994 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001995{
1996 if(length %4 != 0)
1997 {
1998 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1999 return -1;
2000 }
2001 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2002
2003 if(_appData)
2004 {
2005 delete [] _appData;
2006 }
2007
2008 _appSend = true;
2009 _appSubType = subType;
2010 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002011 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002012 _appLength = length;
2013 memcpy(_appData, data, length);
2014 return 0;
2015}
2016
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002017int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002018RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2019{
2020 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2021 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2022
2023 _xrSendVoIPMetric = true;
2024 return 0;
2025}
2026
2027// called under critsect _criticalSectionRTCPSender
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002028int32_t RTCPSender::AddReportBlocks(uint8_t* rtcpbuffer,
2029 uint32_t& pos,
2030 uint8_t& numberOfReportBlocks,
2031 const RTCPReportBlock* received,
2032 const uint32_t NTPsec,
2033 const uint32_t NTPfrac) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002034 // sanity one block
2035 if(pos + 24 >= IP_PACKET_SIZE) {
2036 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2037 "%s invalid argument", __FUNCTION__);
2038 return -1;
2039 }
2040 numberOfReportBlocks = _reportBlocks.size();
2041 if (received) {
2042 // add our multiple RR to numberOfReportBlocks
2043 numberOfReportBlocks++;
2044 }
2045 if (received) {
2046 // answer to the one that sends to me
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +00002047 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002048
2049 // Remote SSRC
2050 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
2051 pos += 4;
2052
2053 // fraction lost
2054 rtcpbuffer[pos++]=received->fractionLost;
2055
2056 // cumulative loss
2057 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2058 received->cumulativeLost);
2059 pos += 3;
2060 // extended highest seq_no, contain the highest sequence number received
2061 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2062 received->extendedHighSeqNum);
2063 pos += 4;
2064
2065 //Jitter
2066 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
2067 pos += 4;
2068
2069 // Last SR timestamp, our NTP time when we received the last report
2070 // This is the value that we read from the send report packet not when we
2071 // received it...
2072 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
2073 pos += 4;
2074
2075 // Delay since last received report,time since we received the report
2076 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2077 received->delaySinceLastSR);
2078 pos += 4;
2079 }
2080 if ((pos + _reportBlocks.size() * 24) >= IP_PACKET_SIZE) {
2081 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2082 "%s invalid argument", __FUNCTION__);
2083 return -1;
2084 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002085 std::map<uint32_t, RTCPReportBlock*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002086 _reportBlocks.begin();
2087
2088 for (; it != _reportBlocks.end(); it++) {
2089 // we can have multiple report block in a conference
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002090 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002091 RTCPReportBlock* reportBlock = it->second;
2092 if (reportBlock) {
2093 // Remote SSRC
2094 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
2095 pos += 4;
2096
2097 // fraction lost
2098 rtcpbuffer[pos++] = reportBlock->fractionLost;
2099
2100 // cumulative loss
2101 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2102 reportBlock->cumulativeLost);
2103 pos += 3;
2104
2105 // extended highest seq_no, contain the highest sequence number received
2106 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2107 reportBlock->extendedHighSeqNum);
2108 pos += 4;
2109
2110 //Jitter
2111 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2112 reportBlock->jitter);
2113 pos += 4;
2114
2115 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2116 reportBlock->lastSR);
2117 pos += 4;
2118
2119 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2120 reportBlock->delaySinceLastSR);
2121 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002122 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002123 }
2124 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00002125}
2126
2127// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002128int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002129RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002130 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002131{
2132 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2133
2134 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2135 {
2136 _sendTMMBN = true;
2137 return 0;
2138 }
2139 return -1;
2140}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002141} // namespace webrtc