blob: 71c47b9412af11b6e5ff75c1c5300c3213df2259 [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 {
elham@webrtc.orgb7eda432013-07-15 21:08:27 +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
elham@webrtc.orgb7eda432013-07-15 21:08:27 +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 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000566 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000567
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000568 if (_reportBlocks.size() >= RTCP_MAX_REPORT_BLOCKS) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000569 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 =
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000574 _reportBlocks.find(SSRC);
575 if (it != _reportBlocks.end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000576 delete it->second;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000577 _reportBlocks.erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000578 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000579 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
580 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000581 _reportBlocks[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000582 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000583}
584
elham@webrtc.orgb7eda432013-07-15 21:08:27 +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 =
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000589 _reportBlocks.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000590
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000591 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;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000595 _reportBlocks.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000596 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,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000601 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000602 const uint32_t NTPsec,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000603 const uint32_t NTPfrac,
604 const RTCPReportBlock* received)
niklase@google.com470e71d2011-07-07 08:21:25 +0000605{
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;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000672 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,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000687 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,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000782 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000783 const uint32_t NTPsec,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000784 const uint32_t NTPfrac,
785 const RTCPReportBlock* received)
niklase@google.com470e71d2011-07-07 08:21:25 +0000786{
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;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000806 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,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000839 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000840 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000841{
elham@webrtc.orgb7eda432013-07-15 21:08:27 +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
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000870RTCPSender::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,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000897 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000898 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
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000946RTCPSender::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,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000993 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000994 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
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001069RTCPSender::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 }
1119 return 0;
1120}
1121
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001122void
1123RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001124{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001125 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001126 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001127}
1128
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001129int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001130RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001131{
1132 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1133 // If the sender is an owner of the TMMBN -> send TMMBR
1134 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1135
niklase@google.com470e71d2011-07-07 08:21:25 +00001136 // get current bounding set from RTCP receiver
1137 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001138 // store in candidateSet, allocates one extra slot
1139 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001140
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001141 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1142 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1143 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001144 int32_t lengthOfBoundingSet
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001145 = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001146
1147 if(lengthOfBoundingSet > 0)
1148 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001149 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001150 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001151 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1152 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001153 {
1154 // do not send the same tuple
1155 return 0;
1156 }
1157 }
1158 if(!tmmbrOwner)
1159 {
1160 // use received bounding set as candidate set
1161 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001162 candidateSet->SetEntry(lengthOfBoundingSet,
1163 _tmmbr_Send,
1164 _packetOH_Send,
1165 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001166 int numCandidates = lengthOfBoundingSet+ 1;
1167
1168 // find bounding set
1169 TMMBRSet* boundingSet = NULL;
1170 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1171 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1172 {
1173 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1174 }
1175 if(!tmmbrOwner)
1176 {
1177 // did not enter bounding set, no meaning to send this request
1178 return 0;
1179 }
1180 }
1181 }
1182
1183 if(_tmmbr_Send)
1184 {
1185 // sanity
1186 if(pos + 20 >= IP_PACKET_SIZE)
1187 {
1188 return -2;
1189 }
1190 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001191 uint8_t FMT = 3;
1192 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1193 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001194
1195 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001196 rtcpbuffer[pos++]=(uint8_t)0;
1197 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001198
1199 // Add our own SSRC
1200 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1201 pos += 4;
1202
1203 // RFC 5104 4.2.1.2. Semantics
1204
1205 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001206 rtcpbuffer[pos++]=(uint8_t)0;
1207 rtcpbuffer[pos++]=(uint8_t)0;
1208 rtcpbuffer[pos++]=(uint8_t)0;
1209 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001210
1211 // Additional Feedback Control Information (FCI)
1212 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1213 pos += 4;
1214
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001215 uint32_t bitRate = _tmmbr_Send*1000;
1216 uint32_t mmbrExp = 0;
1217 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001218 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001219 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001220 {
1221 mmbrExp = i;
1222 break;
1223 }
1224 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001225 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001226
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001227 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1228 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1229 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1230 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001231 }
1232 return 0;
1233}
1234
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001235int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001236RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001237{
1238 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1239 if(boundingSet == NULL)
1240 {
1241 return -1;
1242 }
1243 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001244 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001245 {
1246 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1247 return -2;
1248 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001249 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001250 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001251 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1252 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001253
1254 //Add length later
1255 int posLength = pos;
1256 pos++;
1257 pos++;
1258
1259 // Add our own SSRC
1260 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1261 pos += 4;
1262
1263 // RFC 5104 4.2.2.2. Semantics
1264
1265 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001266 rtcpbuffer[pos++]=(uint8_t)0;
1267 rtcpbuffer[pos++]=(uint8_t)0;
1268 rtcpbuffer[pos++]=(uint8_t)0;
1269 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001270
1271 // Additional Feedback Control Information (FCI)
1272 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001273 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001274 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001275 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001276 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001277 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001278 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1279 pos += 4;
1280
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001281 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1282 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001283 for(int i=0; i<64; i++)
1284 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001285 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001286 {
1287 mmbrExp = i;
1288 break;
1289 }
1290 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001291 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1292 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001293
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001294 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1295 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1296 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1297 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001298 numBoundingSet++;
1299 }
1300 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001301 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1302 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1303 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001304 return 0;
1305}
1306
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001307int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001308RTCPSender::BuildAPP(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001309{
1310 // sanity
1311 if(_appData == NULL)
1312 {
1313 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1314 return -1;
1315 }
1316 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1317 {
1318 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1319 return -2;
1320 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001321 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001322
1323 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001324 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001325
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001326 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1327 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1328 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001329
1330 // Add our own SSRC
1331 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1332 pos += 4;
1333
1334 // Add our application name
1335 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1336 pos += 4;
1337
1338 // Add the data
1339 memcpy(rtcpbuffer +pos, _appData,_appLength);
1340 pos += _appLength;
1341 return 0;
1342}
1343
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001344int32_t
1345RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001346 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001347 const int32_t nackSize,
1348 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001349 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001350{
1351 // sanity
1352 if(pos + 16 >= IP_PACKET_SIZE)
1353 {
1354 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1355 return -2;
1356 }
1357
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001358 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001359 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001360 uint8_t FMT = 1;
1361 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1362 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001363
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001364 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001365 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001366 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001367
1368 // Add our own SSRC
1369 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1370 pos += 4;
1371
1372 // Add the remote SSRC
1373 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1374 pos += 4;
1375
edjee@google.com79b02892013-04-04 19:43:34 +00001376 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001377 // Build NACK bitmasks and write them to the RTCP message.
1378 // The nack list should be sorted and not contain duplicates if one
1379 // wants to build the smallest rtcp nack packet.
1380 int numOfNackFields = 0;
1381 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1382 (IP_PACKET_SIZE - pos) / 4);
1383 int i = 0;
1384 while (i < nackSize && numOfNackFields < maxNackFields) {
1385 stringBuilder.PushNACK(nackList[i]);
1386 uint16_t nack = nackList[i++];
1387 uint16_t bitmask = 0;
1388 while (i < nackSize) {
1389 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1390 if (shift >= 0 && shift <= 15) {
1391 stringBuilder.PushNACK(nackList[i]);
1392 bitmask |= (1 << shift);
1393 ++i;
1394 } else {
1395 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001396 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001397 }
1398 // Write the sequence number and the bitmask to the packet.
1399 assert(pos + 4 < IP_PACKET_SIZE);
1400 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
1401 pos += 2;
1402 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
1403 pos += 2;
1404 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001405 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001406 if (i != nackSize) {
1407 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1408 "Nack list to large for one packet.");
1409 }
1410 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001411 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001412 return 0;
1413}
1414
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001415int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001416RTCPSender::BuildBYE(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001417{
1418 // sanity
1419 if(pos + 8 >= IP_PACKET_SIZE)
1420 {
1421 return -2;
1422 }
1423 if(_includeCSRCs)
1424 {
1425 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001426 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1427 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001428
1429 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001430 rtcpbuffer[pos++]=(uint8_t)0;
1431 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001432
1433 // Add our own SSRC
1434 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1435 pos += 4;
1436
1437 // add CSRCs
1438 for(int i = 0; i < _CSRCs; i++)
1439 {
1440 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1441 pos += 4;
1442 }
1443 } else
1444 {
1445 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001446 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1447 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001448
1449 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001450 rtcpbuffer[pos++]=(uint8_t)0;
1451 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001452
1453 // Add our own SSRC
1454 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1455 pos += 4;
1456 }
1457 return 0;
1458}
1459
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001460int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001461RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001462{
1463 // sanity
1464 if(pos + 44 >= IP_PACKET_SIZE)
1465 {
1466 return -2;
1467 }
1468
1469 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001470 rtcpbuffer[pos++]=(uint8_t)0x80;
1471 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001472
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001473 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001474
1475 // handle length later on
1476 pos++;
1477 pos++;
1478
1479 // Add our own SSRC
1480 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1481 pos += 4;
1482
1483 // Add a VoIP metrics block
1484 rtcpbuffer[pos++]=7;
1485 rtcpbuffer[pos++]=0;
1486 rtcpbuffer[pos++]=0;
1487 rtcpbuffer[pos++]=8;
1488
1489 // Add the remote SSRC
1490 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1491 pos += 4;
1492
1493 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1494 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1495 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1496 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1497
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001498 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1499 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1500 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1501 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001502
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001503 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1504 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1505 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1506 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001507
1508 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1509 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1510 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1511 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1512
1513 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1514 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1515 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1516 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1517
1518 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1519 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001520 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1521 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001522
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001523 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1524 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1525 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1526 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001527
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001528 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1529 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001530 return 0;
1531}
1532
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001533int32_t
stefan@webrtc.org66b2e5c2013-07-05 14:30:48 +00001534RTCPSender::SendRTCP(
1535 uint32_t packetTypeFlags,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001536 const ReceiveStatistics::RtpReceiveStatistics* receive_stats,
stefan@webrtc.org66b2e5c2013-07-05 14:30:48 +00001537 int32_t nackSize,
1538 const uint16_t* nackList,
1539 bool repeat,
1540 uint64_t pictureID)
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 {
1572 // Do we have receive statistics to send?
1573 if (receive_stats)
1574 {
1575 received.fractionLost = receive_stats->fraction_lost;
1576 received.cumulativeLost = receive_stats->cumulative_lost;
1577 received.extendedHighSeqNum =
1578 receive_stats->extended_max_sequence_number;
1579 received.jitter = receive_stats->jitter;
1580 jitterTransmissionOffset = 0;
1581 hasReceived = true;
1582
1583 uint32_t lastReceivedRRNTPsecs = 0;
1584 uint32_t lastReceivedRRNTPfrac = 0;
1585 uint32_t remoteSR = 0;
1586
1587 // ok even if we have not received a SR, we will send 0 in that case
1588 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1589 lastReceivedRRNTPfrac,
1590 remoteSR);
1591
1592 // get our NTP as late as possible to avoid a race
1593 _clock->CurrentNtp(NTPsec, NTPfrac);
1594
1595 // Delay since last received report
1596 uint32_t delaySinceLastReceivedSR = 0;
1597 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
1598 {
1599 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1600 uint32_t now=NTPsec&0x0000FFFF;
1601 now <<=16;
1602 now += (NTPfrac&0xffff0000)>>16;
1603
1604 uint32_t receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
1605 receiveTime <<=16;
1606 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1607
1608 delaySinceLastReceivedSR = now-receiveTime;
1609 }
1610 received.delaySinceLastSR = delaySinceLastReceivedSR;
1611 received.lastSR = remoteSR;
1612 } else
1613 {
1614 // we need to send our NTP even if we dont have received any reports
1615 _clock->CurrentNtp(NTPsec, NTPfrac);
1616 }
1617 }
1618
1619 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1620
1621 if(_TMMBR ) // attach TMMBR to send and receive reports
1622 {
1623 rtcpPacketTypeFlags |= kRtcpTmmbr;
1624 }
1625 if(_appSend)
1626 {
1627 rtcpPacketTypeFlags |= kRtcpApp;
1628 _appSend = false;
1629 }
1630 if(_REMB && _sendREMB)
1631 {
1632 // Always attach REMB to SR if that is configured. Note that REMB is
1633 // only sent on one of the RTP modules in the REMB group.
1634 rtcpPacketTypeFlags |= kRtcpRemb;
1635 }
1636 if(_xrSendVoIPMetric)
1637 {
1638 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1639 _xrSendVoIPMetric = false;
1640 }
1641 if(_sendTMMBN) // set when having received a TMMBR
1642 {
1643 rtcpPacketTypeFlags |= kRtcpTmmbn;
1644 _sendTMMBN = false;
1645 }
1646
1647 if(_method == kRtcpCompound)
1648 {
1649 if(_sending)
1650 {
1651 rtcpPacketTypeFlags |= kRtcpSr;
1652 } else
1653 {
1654 rtcpPacketTypeFlags |= kRtcpRr;
1655 }
1656 if (_IJ && hasReceived)
1657 {
1658 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1659 }
1660 } else if(_method == kRtcpNonCompound)
1661 {
1662 if(rtcpPacketTypeFlags & kRtcpReport)
1663 {
1664 if(_sending)
1665 {
1666 rtcpPacketTypeFlags |= kRtcpSr;
1667 } else
1668 {
1669 rtcpPacketTypeFlags |= kRtcpRr;
1670 }
1671 }
1672 }
1673 if( rtcpPacketTypeFlags & kRtcpRr ||
1674 rtcpPacketTypeFlags & kRtcpSr)
1675 {
1676 // generate next time to send a RTCP report
1677 // seeded from RTP constructor
1678 int32_t random = rand() % 1000;
1679 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1680
1681 if(_audio)
1682 {
1683 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
1684 }else
1685 {
1686 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1687 if(_sending)
1688 {
1689 // calc bw for video 360/sendBW in kbit/s
1690 uint32_t sendBitrateKbit = 0;
1691 uint32_t videoRate = 0;
1692 uint32_t fecRate = 0;
1693 uint32_t nackRate = 0;
1694 _rtpRtcp.BitrateSent(&sendBitrateKbit,
1695 &videoRate,
1696 &fecRate,
1697 &nackRate);
1698 sendBitrateKbit /= 1000;
1699 if(sendBitrateKbit != 0)
1700 {
1701 minIntervalMs = 360000/sendBitrateKbit;
1702 }
1703 }
1704 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1705 {
1706 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1707 }
1708 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1709 }
1710 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1711 }
1712
1713 // if the data does not fitt in the packet we fill it as much as possible
1714 int32_t buildVal = 0;
1715
1716 if(rtcpPacketTypeFlags & kRtcpSr)
1717 {
1718 if(hasReceived)
1719 {
1720 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
1721 } else
1722 {
1723 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac);
1724 }
1725 if(buildVal == -1)
1726 {
1727 return -1; // error
1728
1729 }else if(buildVal == -2)
1730 {
1731 break; // out of buffer
1732 }
1733 buildVal = BuildSDEC(rtcpbuffer, pos);
1734 if(buildVal == -1)
1735 {
1736 return -1; // error
1737
1738 }else if(buildVal == -2)
1739 {
1740 break; // out of buffer
1741 }
1742
1743 }else if(rtcpPacketTypeFlags & kRtcpRr)
1744 {
1745 if(hasReceived)
1746 {
1747 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
1748 }else
1749 {
1750 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
1751 }
1752 if(buildVal == -1)
1753 {
1754 return -1; // error
1755
1756 }else if(buildVal == -2)
1757 {
1758 break; // out of buffer
1759 }
1760 // only of set
1761 if(_CNAME[0] != 0)
1762 {
1763 buildVal = BuildSDEC(rtcpbuffer, pos);
1764 if(buildVal == -1)
1765 {
1766 return -1; // error
1767 }
1768 }
1769 }
1770 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1771 {
1772 // If present, this RTCP packet must be placed after a
1773 // receiver report.
1774 buildVal = BuildExtendedJitterReport(rtcpbuffer,
1775 pos,
1776 jitterTransmissionOffset);
1777 if(buildVal == -1)
1778 {
1779 return -1; // error
1780 }
1781 else if(buildVal == -2)
1782 {
1783 break; // out of buffer
1784 }
1785 }
1786 if(rtcpPacketTypeFlags & kRtcpPli)
1787 {
1788 buildVal = BuildPLI(rtcpbuffer, pos);
1789 if(buildVal == -1)
1790 {
1791 return -1; // error
1792
1793 }else if(buildVal == -2)
1794 {
1795 break; // out of buffer
1796 }
1797 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
1798 _pliCount++;
1799 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC, _pliCount);
1800 }
1801 if(rtcpPacketTypeFlags & kRtcpFir)
1802 {
1803 buildVal = BuildFIR(rtcpbuffer, pos, repeat);
1804 if(buildVal == -1)
1805 {
1806 return -1; // error
1807
1808 }else if(buildVal == -2)
1809 {
1810 break; // out of buffer
1811 }
1812 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
1813 _fullIntraRequestCount++;
1814 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
1815 _fullIntraRequestCount);
1816 }
1817 if(rtcpPacketTypeFlags & kRtcpSli)
1818 {
1819 buildVal = BuildSLI(rtcpbuffer, pos, (uint8_t)pictureID);
1820 if(buildVal == -1)
1821 {
1822 return -1; // error
1823
1824 }else if(buildVal == -2)
1825 {
1826 break; // out of buffer
1827 }
1828 }
1829 if(rtcpPacketTypeFlags & kRtcpRpsi)
1830 {
1831 const int8_t payloadType = _rtpRtcp.SendPayloadType();
1832 if(payloadType == -1)
1833 {
1834 return -1;
1835 }
1836 buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (uint8_t)payloadType);
1837 if(buildVal == -1)
1838 {
1839 return -1; // error
1840
1841 }else if(buildVal == -2)
1842 {
1843 break; // out of buffer
1844 }
1845 }
1846 if(rtcpPacketTypeFlags & kRtcpRemb)
1847 {
1848 buildVal = BuildREMB(rtcpbuffer, pos);
1849 if(buildVal == -1)
1850 {
1851 return -1; // error
1852
1853 }else if(buildVal == -2)
1854 {
1855 break; // out of buffer
1856 }
1857 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1858 }
1859 if(rtcpPacketTypeFlags & kRtcpBye)
1860 {
1861 buildVal = BuildBYE(rtcpbuffer, pos);
1862 if(buildVal == -1)
1863 {
1864 return -1; // error
1865
1866 }else if(buildVal == -2)
1867 {
1868 break; // out of buffer
1869 }
1870 }
1871 if(rtcpPacketTypeFlags & kRtcpApp)
1872 {
1873 buildVal = BuildAPP(rtcpbuffer, pos);
1874 if(buildVal == -1)
1875 {
1876 return -1; // error
1877
1878 }else if(buildVal == -2)
1879 {
1880 break; // out of buffer
1881 }
1882 }
1883 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1884 {
1885 buildVal = BuildTMMBR(rtcpbuffer, pos);
1886 if(buildVal == -1)
1887 {
1888 return -1; // error
1889
1890 }else if(buildVal == -2)
1891 {
1892 break; // out of buffer
1893 }
1894 }
1895 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1896 {
1897 buildVal = BuildTMMBN(rtcpbuffer, pos);
1898 if(buildVal == -1)
1899 {
1900 return -1; // error
1901
1902 }else if(buildVal == -2)
1903 {
1904 break; // out of buffer
1905 }
1906 }
1907 if(rtcpPacketTypeFlags & kRtcpNack)
1908 {
1909 std::string nackString;
1910 buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList,
1911 &nackString);
1912 if(buildVal == -1)
1913 {
1914 return -1; // error
1915
1916 }else if(buildVal == -2)
1917 {
1918 break; // out of buffer
1919 }
1920 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
1921 "nacks", TRACE_STR_COPY(nackString.c_str()));
1922 _nackCount++;
1923 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC, _nackCount);
1924 }
1925 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1926 {
1927 buildVal = BuildVoIPMetric(rtcpbuffer, pos);
1928 if(buildVal == -1)
1929 {
1930 return -1; // error
1931
1932 }else if(buildVal == -2)
1933 {
1934 break; // out of buffer
1935 }
1936 }
1937 }while (false);
1938 // Sanity don't send empty packets.
1939 if (pos == 0)
1940 {
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001941 return -1;
1942 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001943 return SendToNetwork(rtcpbuffer, (uint16_t)pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001944}
1945
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001946int32_t
1947RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
1948 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001949{
1950 CriticalSectionScoped lock(_criticalSectionTransport);
1951 if(_cbTransport)
1952 {
1953 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1954 {
1955 return 0;
1956 }
1957 }
1958 return -1;
1959}
1960
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001961int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00001962RTCPSender::SetCSRCStatus(const bool include)
1963{
1964 _includeCSRCs = include;
1965 return 0;
1966}
1967
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001968int32_t
1969RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
1970 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00001971{
1972 if(arrLength > kRtpCsrcSize)
1973 {
1974 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1975 assert(false);
1976 return -1;
1977 }
1978
1979 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1980
1981 for(int i = 0; i < arrLength;i++)
1982 {
1983 _CSRC[i] = arrOfCSRC[i];
1984 }
1985 _CSRCs = arrLength;
1986 return 0;
1987}
1988
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001989int32_t
1990RTCPSender::SetApplicationSpecificData(const uint8_t subType,
1991 const uint32_t name,
1992 const uint8_t* data,
1993 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001994{
1995 if(length %4 != 0)
1996 {
1997 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1998 return -1;
1999 }
2000 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2001
2002 if(_appData)
2003 {
2004 delete [] _appData;
2005 }
2006
2007 _appSend = true;
2008 _appSubType = subType;
2009 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002010 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002011 _appLength = length;
2012 memcpy(_appData, data, length);
2013 return 0;
2014}
2015
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002016int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002017RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2018{
2019 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2020 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2021
2022 _xrSendVoIPMetric = true;
2023 return 0;
2024}
2025
2026// called under critsect _criticalSectionRTCPSender
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002027int32_t RTCPSender::AddReportBlocks(uint8_t* rtcpbuffer,
2028 uint32_t& pos,
2029 uint8_t& numberOfReportBlocks,
2030 const RTCPReportBlock* received,
2031 const uint32_t NTPsec,
2032 const uint32_t NTPfrac) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002033 // sanity one block
2034 if(pos + 24 >= IP_PACKET_SIZE) {
2035 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2036 "%s invalid argument", __FUNCTION__);
2037 return -1;
2038 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002039 numberOfReportBlocks = _reportBlocks.size();
2040 if (received) {
2041 // add our multiple RR to numberOfReportBlocks
2042 numberOfReportBlocks++;
2043 }
2044 if (received) {
2045 // answer to the one that sends to me
2046 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
2047
2048 // Remote SSRC
2049 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
2050 pos += 4;
2051
2052 // fraction lost
2053 rtcpbuffer[pos++]=received->fractionLost;
2054
2055 // cumulative loss
2056 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2057 received->cumulativeLost);
2058 pos += 3;
2059 // extended highest seq_no, contain the highest sequence number received
2060 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2061 received->extendedHighSeqNum);
2062 pos += 4;
2063
2064 //Jitter
2065 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
2066 pos += 4;
2067
2068 // Last SR timestamp, our NTP time when we received the last report
2069 // This is the value that we read from the send report packet not when we
2070 // received it...
2071 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
2072 pos += 4;
2073
2074 // Delay since last received report,time since we received the report
2075 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2076 received->delaySinceLastSR);
2077 pos += 4;
2078 }
2079 if ((pos + _reportBlocks.size() * 24) >= IP_PACKET_SIZE) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002080 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2081 "%s invalid argument", __FUNCTION__);
2082 return -1;
2083 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002084 std::map<uint32_t, RTCPReportBlock*>::iterator it =
2085 _reportBlocks.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002086
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002087 for (; it != _reportBlocks.end(); it++) {
2088 // we can have multiple report block in a conference
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002089 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002090 RTCPReportBlock* reportBlock = it->second;
2091 if (reportBlock) {
2092 // Remote SSRC
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002093 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
2094 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002095
2096 // fraction lost
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002097 rtcpbuffer[pos++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002098
2099 // cumulative loss
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002100 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002101 reportBlock->cumulativeLost);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002102 pos += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002103
2104 // extended highest seq_no, contain the highest sequence number received
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002105 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002106 reportBlock->extendedHighSeqNum);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002107 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002108
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002109 //Jitter
2110 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002111 reportBlock->jitter);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002112 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002113
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002114 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002115 reportBlock->lastSR);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002116 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002117
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002118 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002119 reportBlock->delaySinceLastSR);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002120 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002121 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002122 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002123 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00002124}
2125
2126// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002127int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002128RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002129 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002130{
2131 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2132
2133 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2134 {
2135 _sendTMMBN = true;
2136 return 0;
2137 }
2138 return -1;
2139}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002140} // namespace webrtc