blob: c7bd5ac6a03af2742d8db479f15b32822e4d22d7 [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.orgf3e4cee2013-07-31 15:17:19 +000034NACKStringBuilder::~NACKStringBuilder() {}
35
pbos@webrtc.org2f446732013-04-08 11:08:41 +000036void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000037{
38 if (_count == 0)
39 {
40 _stream << nack;
41 } else if (nack == _prevNack + 1)
42 {
43 _consecutive = true;
44 } else
45 {
46 if (_consecutive)
47 {
48 _stream << "-" << _prevNack;
49 _consecutive = false;
50 }
51 _stream << "," << nack;
52 }
53 _count++;
54 _prevNack = nack;
55}
56
57std::string NACKStringBuilder::GetResult()
58{
59 if (_consecutive)
60 {
61 _stream << "-" << _prevNack;
62 _consecutive = false;
63 }
64 return _stream.str();
65}
66
pbos@webrtc.org2f446732013-04-08 11:08:41 +000067RTCPSender::RTCPSender(const int32_t id,
niklase@google.com470e71d2011-07-07 08:21:25 +000068 const bool audio,
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000069 Clock* clock,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +000070 ModuleRtpRtcpImpl* owner) :
niklase@google.com470e71d2011-07-07 08:21:25 +000071 _id(id),
72 _audio(audio),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000073 _clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000074 _method(kRtcpOff),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000075 _rtpRtcp(*owner),
henrike@webrtc.org65573f22011-12-13 19:17:27 +000076 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000077 _cbTransport(NULL),
78
henrike@webrtc.org65573f22011-12-13 19:17:27 +000079 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000080 _usingNack(false),
81 _sending(false),
82 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000083 _REMB(false),
84 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000085 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +000086 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000087 _nextTimeToSendRTCP(0),
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000088 start_timestamp_(0),
89 last_rtp_timestamp_(0),
90 last_frame_capture_time_ms_(-1),
niklase@google.com470e71d2011-07-07 08:21:25 +000091 _SSRC(0),
92 _remoteSSRC(0),
93 _CNAME(),
elham@webrtc.orgb7eda432013-07-15 21:08:27 +000094 _reportBlocks(),
niklase@google.com470e71d2011-07-07 08:21:25 +000095 _csrcCNAMEs(),
96
stefan@webrtc.org7da34592013-04-09 14:56:29 +000097 _cameraDelayMS(0),
98
niklase@google.com470e71d2011-07-07 08:21:25 +000099 _lastSendReport(),
100 _lastRTCPTime(),
101
102 _CSRCs(0),
103 _CSRC(),
104 _includeCSRCs(true),
105
106 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000107
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000108 _lengthRembSSRC(0),
109 _sizeRembSSRC(0),
110 _rembSSRC(NULL),
111 _rembBitrate(0),
112
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000113 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000114 _tmmbr_Send(0),
115 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000116
117 _appSend(false),
118 _appSubType(0),
119 _appName(),
120 _appData(NULL),
121 _appLength(0),
122 _xrSendVoIPMetric(false),
edjee@google.com79b02892013-04-04 19:43:34 +0000123 _xrVoIPMetric(),
124 _nackCount(0),
125 _pliCount(0),
126 _fullIntraRequestCount(0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000127{
128 memset(_CNAME, 0, sizeof(_CNAME));
129 memset(_lastSendReport, 0, sizeof(_lastSendReport));
130 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
131
132 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
133}
134
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000135RTCPSender::~RTCPSender() {
136 delete [] _rembSSRC;
137 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000138
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000139 while (!_reportBlocks.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000140 std::map<uint32_t, RTCPReportBlock*>::iterator it =
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000141 _reportBlocks.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000142 delete it->second;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000143 _reportBlocks.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000144 }
145 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000146 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000147 _csrcCNAMEs.begin();
148 delete it->second;
149 _csrcCNAMEs.erase(it);
150 }
151 delete _criticalSectionTransport;
152 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000153
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000154 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000155}
156
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000157int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000158RTCPSender::Init()
159{
160 CriticalSectionScoped lock(_criticalSectionRTCPSender);
161
162 _method = kRtcpOff;
163 _cbTransport = NULL;
164 _usingNack = false;
165 _sending = false;
166 _sendTMMBN = false;
167 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000168 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000169 _REMB = false;
170 _sendREMB = false;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000171 last_rtp_timestamp_ = 0;
172 last_frame_capture_time_ms_ = -1;
173 start_timestamp_ = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000174 _SSRC = 0;
175 _remoteSSRC = 0;
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000176 _cameraDelayMS = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000177 _sequenceNumberFIR = 0;
178 _tmmbr_Send = 0;
179 _packetOH_Send = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000180 _nextTimeToSendRTCP = 0;
181 _CSRCs = 0;
182 _appSend = false;
183 _appSubType = 0;
184
185 if(_appData)
186 {
187 delete [] _appData;
188 _appData = NULL;
189 }
190 _appLength = 0;
191
192 _xrSendVoIPMetric = false;
193
194 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
195 memset(_CNAME, 0, sizeof(_CNAME));
196 memset(_lastSendReport, 0, sizeof(_lastSendReport));
197 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
edjee@google.com79b02892013-04-04 19:43:34 +0000198
199 _nackCount = 0;
200 _pliCount = 0;
201 _fullIntraRequestCount = 0;
202
niklase@google.com470e71d2011-07-07 08:21:25 +0000203 return 0;
204}
205
206void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000207RTCPSender::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +0000208{
209 _id = id;
210}
211
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000212int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000213RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
214{
215 CriticalSectionScoped lock(_criticalSectionTransport);
216 _cbTransport = outgoingTransport;
217 return 0;
218}
219
220RTCPMethod
221RTCPSender::Status() const
222{
223 CriticalSectionScoped lock(_criticalSectionRTCPSender);
224 return _method;
225}
226
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000227int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000228RTCPSender::SetRTCPStatus(const RTCPMethod method)
229{
230 CriticalSectionScoped lock(_criticalSectionRTCPSender);
231 if(method != kRtcpOff)
232 {
233 if(_audio)
234 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000235 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000236 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000237 } else
238 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000239 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000240 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000241 }
242 }
243 _method = method;
244 return 0;
245}
246
247bool
248RTCPSender::Sending() const
249{
250 CriticalSectionScoped lock(_criticalSectionRTCPSender);
251 return _sending;
252}
253
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000254int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000255RTCPSender::SetSendingStatus(const bool sending)
256{
257 bool sendRTCPBye = false;
258 {
259 CriticalSectionScoped lock(_criticalSectionRTCPSender);
260
261 if(_method != kRtcpOff)
262 {
263 if(sending == false && _sending == true)
264 {
265 // Trigger RTCP bye
266 sendRTCPBye = true;
267 }
268 }
269 _sending = sending;
270 }
271 if(sendRTCPBye)
272 {
tnakamura@webrtc.orgaa4d96a2013-07-16 19:25:04 +0000273 return SendRTCP(kRtcpBye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000274 }
275 return 0;
276}
277
278bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000279RTCPSender::REMB() const
280{
281 CriticalSectionScoped lock(_criticalSectionRTCPSender);
282 return _REMB;
283}
284
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000285int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000286RTCPSender::SetREMBStatus(const bool enable)
287{
288 CriticalSectionScoped lock(_criticalSectionRTCPSender);
289 _REMB = enable;
290 return 0;
291}
292
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000293int32_t
294RTCPSender::SetREMBData(const uint32_t bitrate,
295 const uint8_t numberOfSSRC,
296 const uint32_t* SSRC)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000297{
298 CriticalSectionScoped lock(_criticalSectionRTCPSender);
299 _rembBitrate = bitrate;
300
301 if(_sizeRembSSRC < numberOfSSRC)
302 {
303 delete [] _rembSSRC;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000304 _rembSSRC = new uint32_t[numberOfSSRC];
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000305 _sizeRembSSRC = numberOfSSRC;
306 }
307
308 _lengthRembSSRC = numberOfSSRC;
309 for (int i = 0; i < numberOfSSRC; i++)
310 {
311 _rembSSRC[i] = SSRC[i];
312 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000313 _sendREMB = true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000314 return 0;
315}
316
317bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000318RTCPSender::TMMBR() const
319{
320 CriticalSectionScoped lock(_criticalSectionRTCPSender);
321 return _TMMBR;
322}
323
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000324int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000325RTCPSender::SetTMMBRStatus(const bool enable)
326{
327 CriticalSectionScoped lock(_criticalSectionRTCPSender);
328 _TMMBR = enable;
329 return 0;
330}
331
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000332bool
333RTCPSender::IJ() const
334{
335 CriticalSectionScoped lock(_criticalSectionRTCPSender);
336 return _IJ;
337}
338
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000339int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000340RTCPSender::SetIJStatus(const bool enable)
341{
342 CriticalSectionScoped lock(_criticalSectionRTCPSender);
343 _IJ = enable;
344 return 0;
345}
346
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000347void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
348 start_timestamp_ = start_timestamp;
349}
350
351void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
352 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000353 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000354 last_rtp_timestamp_ = rtp_timestamp;
355 if (capture_time_ms < 0) {
356 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000357 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000358 } else {
359 last_frame_capture_time_ms_ = capture_time_ms;
360 }
361}
362
niklase@google.com470e71d2011-07-07 08:21:25 +0000363void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000364RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000365{
366 CriticalSectionScoped lock(_criticalSectionRTCPSender);
367
368 if(_SSRC != 0)
369 {
370 // not first SetSSRC, probably due to a collision
371 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000372 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000373 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000374 }
375 _SSRC = ssrc;
376}
377
tnakamura@webrtc.orgaa4d96a2013-07-16 19:25:04 +0000378int32_t
379RTCPSender::SetRemoteSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000380{
381 CriticalSectionScoped lock(_criticalSectionRTCPSender);
382 _remoteSSRC = ssrc;
tnakamura@webrtc.orgaa4d96a2013-07-16 19:25:04 +0000383 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000384}
385
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000386int32_t
387RTCPSender::SetCameraDelay(const int32_t delayMS)
388{
389 CriticalSectionScoped lock(_criticalSectionRTCPSender);
390 if(delayMS > 1000 || delayMS < -1000)
391 {
392 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
393 return -1;
394 }
395 _cameraDelayMS = delayMS;
396 return 0;
397}
398
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000399int32_t RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000400 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000401 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000402 cName[RTCP_CNAME_SIZE - 1] = 0;
403 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000404 return 0;
405}
406
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000407int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000408 if (!cName)
409 return -1;
410
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000411 CriticalSectionScoped lock(_criticalSectionRTCPSender);
412 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
413 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
414 return 0;
415}
416
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000417int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
418 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000419 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000420 CriticalSectionScoped lock(_criticalSectionRTCPSender);
421 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
422 return -1;
423 }
424 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000425 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
426 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000427 _csrcCNAMEs[SSRC] = ptr;
428 return 0;
429}
430
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000431int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000432 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000433 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000434 _csrcCNAMEs.find(SSRC);
435
436 if (it == _csrcCNAMEs.end()) {
437 return -1;
438 }
439 delete it->second;
440 _csrcCNAMEs.erase(it);
441 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000442}
443
444bool
445RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
446{
447/*
448 For audio we use a fix 5 sec interval
449
450 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
451 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
452
453
454From RFC 3550
455
456 MAX RTCP BW is 5% if the session BW
457 A send report is approximately 65 bytes inc CNAME
458 A report report is approximately 28 bytes
459
460 The RECOMMENDED value for the reduced minimum in seconds is 360
461 divided by the session bandwidth in kilobits/second. This minimum
462 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
463
464 If the participant has not yet sent an RTCP packet (the variable
465 initial is true), the constant Tmin is set to 2.5 seconds, else it
466 is set to 5 seconds.
467
468 The interval between RTCP packets is varied randomly over the
469 range [0.5,1.5] times the calculated interval to avoid unintended
470 synchronization of all participants
471
472 if we send
473 If the participant is a sender (we_sent true), the constant C is
474 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
475 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
476 number of senders.
477
478 if we receive only
479 If we_sent is not true, the constant C is set
480 to the average RTCP packet size divided by 75% of the RTCP
481 bandwidth. The constant n is set to the number of receivers
482 (members - senders). If the number of senders is greater than
483 25%, senders and receivers are treated together.
484
485 reconsideration NOT required for peer-to-peer
486 "timer reconsideration" is
487 employed. This algorithm implements a simple back-off mechanism
488 which causes users to hold back RTCP packet transmission if the
489 group sizes are increasing.
490
491 n = number of members
492 C = avg_size/(rtcpBW/4)
493
494 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
495
496 4. The calculated interval T is set to a number uniformly distributed
497 between 0.5 and 1.5 times the deterministic calculated interval.
498
499 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
500 for the fact that the timer reconsideration algorithm converges to
501 a value of the RTCP bandwidth below the intended average
502*/
503
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000504 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000505
506 CriticalSectionScoped lock(_criticalSectionRTCPSender);
507
niklase@google.com470e71d2011-07-07 08:21:25 +0000508 if(_method == kRtcpOff)
509 {
510 return false;
511 }
512
niklase@google.com470e71d2011-07-07 08:21:25 +0000513 if(!_audio && sendKeyframeBeforeRTP)
514 {
515 // for video key-frames we want to send the RTCP before the large key-frame
516 // if we have a 100 ms margin
517 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
518 }
519
520 if(now > _nextTimeToSendRTCP)
521 {
522 return true;
523
524 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
525 {
526 // wrap
527 return true;
528 }
529 return false;
530}
531
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000532uint32_t
533RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000534{
535 CriticalSectionScoped lock(_criticalSectionRTCPSender);
536
537 lastRTCPTime = _lastRTCPTime[0];
538 return _lastSendReport[0];
539}
540
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000541uint32_t
542RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000543{
544 CriticalSectionScoped lock(_criticalSectionRTCPSender);
545
546 // This is only saved when we are the sender
547 if((_lastSendReport[0] == 0) || (sendReport == 0))
548 {
549 return 0; // will be ignored
550 } else
551 {
552 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
553 {
554 if( _lastSendReport[i] == sendReport)
555 {
556 return _lastRTCPTime[i];
557 }
558 }
559 }
560 return 0;
561}
562
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000563int32_t RTCPSender::AddReportBlock(const uint32_t SSRC,
564 const RTCPReportBlock* reportBlock) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000565 if (reportBlock == NULL) {
566 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
567 "%s invalid argument", __FUNCTION__);
568 return -1;
569 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000570 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000571
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000572 if (_reportBlocks.size() >= RTCP_MAX_REPORT_BLOCKS) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000573 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
574 "%s invalid argument", __FUNCTION__);
575 return -1;
576 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000577 std::map<uint32_t, RTCPReportBlock*>::iterator it =
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000578 _reportBlocks.find(SSRC);
579 if (it != _reportBlocks.end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000580 delete it->second;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000581 _reportBlocks.erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000582 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000583 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
584 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000585 _reportBlocks[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000586 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000587}
588
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000589int32_t RTCPSender::RemoveReportBlock(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000590 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000591
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000592 std::map<uint32_t, RTCPReportBlock*>::iterator it =
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000593 _reportBlocks.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000594
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000595 if (it == _reportBlocks.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000596 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000597 }
598 delete it->second;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000599 _reportBlocks.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000600 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000601}
602
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000603int32_t
604RTCPSender::BuildSR(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000605 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000606 const uint32_t NTPsec,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000607 const uint32_t NTPfrac,
608 const RTCPReportBlock* received)
niklase@google.com470e71d2011-07-07 08:21:25 +0000609{
610 // sanity
611 if(pos + 52 >= IP_PACKET_SIZE)
612 {
613 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
614 return -2;
615 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000616 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000617
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000618 uint32_t posNumberOfReportBlocks = pos;
619 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000620
621 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000622 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000623
624 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
625 {
626 // shift old
627 _lastSendReport[i+1] = _lastSendReport[i];
628 _lastRTCPTime[i+1] =_lastRTCPTime[i];
629 }
630
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000631 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000632 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000633
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000634 uint32_t freqHz = 90000; // For video
635 if(_audio) {
636 freqHz = _rtpRtcp.CurrentSendFrequencyHz();
niklase@google.com470e71d2011-07-07 08:21:25 +0000637 }
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000638
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000639 // The timestamp of this RTCP packet should be estimated as the timestamp of
640 // the frame being captured at this moment. We are calculating that
641 // timestamp as the last frame's timestamp + the time since the last frame
642 // was captured.
643 {
644 // Needs protection since this method is called on the process thread.
645 CriticalSectionScoped lock(_criticalSectionRTCPSender);
646 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
647 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
648 (freqHz / 1000);
649 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000650
651 // Add sender data
652 // Save for our length field
653 pos++;
654 pos++;
655
656 // Add our own SSRC
657 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
658 pos += 4;
659 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000660 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000661 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000662 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000663 pos += 4;
664 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
665 pos += 4;
666
667 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000668 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000669 pos += 4;
670
671 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000672 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000673 pos += 4;
674
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000675 uint8_t numberOfReportBlocks = 0;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000676 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000677 if(retVal < 0)
678 {
679 //
680 return retVal ;
681 }
682 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
683
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000684 uint16_t len = uint16_t((pos/4) -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000685 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
686 return 0;
687}
688
689
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000690int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000691 uint32_t& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000692 size_t lengthCname = strlen(_CNAME);
693 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000694
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000695 // sanity
696 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
697 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
698 "%s invalid argument", __FUNCTION__);
699 return -2;
700 }
701 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000702
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000703 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000704 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
705 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000706
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000707 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000708 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000709 pos++;
710 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000711
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000712 // Add our own SSRC
713 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
714 pos += 4;
715
716 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000717 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000718
719 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000720 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000721
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000722 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000723
724 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
725 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000726 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000727
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000728 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000729 // We must have a zero field even if we have an even multiple of 4 bytes
730 if ((pos % 4) == 0) {
731 padding++;
732 rtcpbuffer[pos++]=0;
733 }
734 while ((pos % 4) != 0) {
735 padding++;
736 rtcpbuffer[pos++]=0;
737 }
738 SDESLength += padding;
739
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000740 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000741 _csrcCNAMEs.begin();
742
743 for(; it != _csrcCNAMEs.end(); it++) {
744 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000745 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000746
747 // Add SSRC
748 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000749 pos += 4;
750
751 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000752 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000753
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000754 size_t length = strlen(cname->name);
755 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000756
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000757 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000758 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000759
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000760 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000761
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000762 pos += length;
763 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000764 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000765
766 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000767 if((pos % 4) == 0){
768 padding++;
769 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000770 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000771 while((pos % 4) != 0){
772 padding++;
773 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000774 }
775 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000776 }
777 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000778 uint16_t buffer_length = (SDESLength / 4) - 1;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000779 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
780 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000781 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000782}
783
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000784int32_t
785RTCPSender::BuildRR(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000786 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000787 const uint32_t NTPsec,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000788 const uint32_t NTPfrac,
789 const RTCPReportBlock* received)
niklase@google.com470e71d2011-07-07 08:21:25 +0000790{
791 // sanity one block
792 if(pos + 32 >= IP_PACKET_SIZE)
793 {
794 return -2;
795 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000796 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000797
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000798 rtcpbuffer[pos++]=(uint8_t)0x80;
799 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000800
801 // Save for our length field
802 pos++;
803 pos++;
804
805 // Add our own SSRC
806 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
807 pos += 4;
808
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000809 uint8_t numberOfReportBlocks = 0;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000810 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000811 if(retVal < 0)
812 {
813 return retVal;
814 }
815 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
816
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000817 uint16_t len = uint16_t((pos)/4 -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000818 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
819 return 0;
820}
821
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000822// From RFC 5450: Transmission Time Offsets in RTP Streams.
823// 0 1 2 3
824// 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
825// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
826// hdr |V=2|P| RC | PT=IJ=195 | length |
827// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
828// | inter-arrival jitter |
829// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
830// . .
831// . .
832// . .
833// | inter-arrival jitter |
834// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
835//
836// If present, this RTCP packet must be placed after a receiver report
837// (inside a compound RTCP packet), and MUST have the same value for RC
838// (reception report count) as the receiver report.
839
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000840int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000841RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000842 uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000843 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000844 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000845{
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000846 if (_reportBlocks.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000847 {
848 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
849 return 0;
850 }
851
852 // sanity
853 if(pos + 8 >= IP_PACKET_SIZE)
854 {
855 return -2;
856 }
857 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000858 uint8_t RC = 1;
859 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
860 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000861
862 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000863 rtcpbuffer[pos++]=(uint8_t)0;
864 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000865
866 // Add inter-arrival jitter
867 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
868 jitterTransmissionTimeOffset);
869 pos += 4;
870 return 0;
871}
872
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000873int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000874RTCPSender::BuildPLI(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000875{
876 // sanity
877 if(pos + 12 >= IP_PACKET_SIZE)
878 {
879 return -2;
880 }
881 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000882 uint8_t FMT = 1;
883 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
884 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000885
886 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000887 rtcpbuffer[pos++]=(uint8_t)0;
888 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000889
890 // Add our own SSRC
891 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
892 pos += 4;
893
894 // Add the remote SSRC
895 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
896 pos += 4;
897 return 0;
898}
899
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000900int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000901 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000902 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000903 // sanity
904 if(pos + 20 >= IP_PACKET_SIZE) {
905 return -2;
906 }
907 if (!repeat) {
908 _sequenceNumberFIR++; // do not increase if repetition
909 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000910
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000911 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000912 uint8_t FMT = 4;
913 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
914 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000915
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000916 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000917 rtcpbuffer[pos++] = (uint8_t)0;
918 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000919
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000920 // Add our own SSRC
921 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
922 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000923
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000924 // RFC 5104 4.3.1.2. Semantics
925 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000926 rtcpbuffer[pos++] = (uint8_t)0;
927 rtcpbuffer[pos++] = (uint8_t)0;
928 rtcpbuffer[pos++] = (uint8_t)0;
929 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000930
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000931 // Additional Feedback Control Information (FCI)
932 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
933 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000934
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000935 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
936 rtcpbuffer[pos++] = (uint8_t)0;
937 rtcpbuffer[pos++] = (uint8_t)0;
938 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000939 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000940}
941
942/*
943 0 1 2 3
944 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
945 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
946 | First | Number | PictureID |
947 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
948*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000949int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000950RTCPSender::BuildSLI(uint8_t* rtcpbuffer, uint32_t& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000951{
952 // sanity
953 if(pos + 16 >= IP_PACKET_SIZE)
954 {
955 return -2;
956 }
957 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000958 uint8_t FMT = 2;
959 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
960 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000961
962 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000963 rtcpbuffer[pos++]=(uint8_t)0;
964 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000965
966 // Add our own SSRC
967 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
968 pos += 4;
969
970 // Add the remote SSRC
971 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
972 pos += 4;
973
974 // Add first, number & picture ID 6 bits
975 // first = 0, 13 - bits
976 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000977 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000978 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
979 pos += 4;
980 return 0;
981}
982
983/*
984 0 1 2 3
985 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
986 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
987 | PB |0| Payload Type| Native RPSI bit string |
988 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
989 | defined per codec ... | Padding (0) |
990 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
991*/
992/*
993* Note: not generic made for VP8
994*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000995int32_t
996RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000997 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000998 const uint64_t pictureID,
999 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +00001000{
1001 // sanity
1002 if(pos + 24 >= IP_PACKET_SIZE)
1003 {
1004 return -2;
1005 }
1006 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001007 uint8_t FMT = 3;
1008 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1009 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001010
1011 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001012 uint32_t bitsRequired = 7;
1013 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001014 while((pictureID>>bitsRequired) > 0)
1015 {
1016 bitsRequired += 7;
1017 bytesRequired++;
1018 }
1019
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001020 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001021 if(bytesRequired > 6)
1022 {
1023 size = 5;
1024 } else if(bytesRequired > 2)
1025 {
1026 size = 4;
1027 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001028 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001029 rtcpbuffer[pos++]=size;
1030
1031 // Add our own SSRC
1032 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1033 pos += 4;
1034
1035 // Add the remote SSRC
1036 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1037 pos += 4;
1038
1039 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001040 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001041 if(paddingBytes == 4)
1042 {
1043 paddingBytes = 0;
1044 }
1045 // add padding length in bits
1046 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1047 pos++;
1048
1049 // add payload type
1050 rtcpbuffer[pos] = payloadType;
1051 pos++;
1052
1053 // add picture ID
1054 for(int i = bytesRequired-1; i > 0; i--)
1055 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001056 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001057 pos++;
1058 }
1059 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001060 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001061 pos++;
1062
1063 // add padding
1064 for(int j = 0; j <paddingBytes; j++)
1065 {
1066 rtcpbuffer[pos] = 0;
1067 pos++;
1068 }
1069 return 0;
1070}
1071
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001072int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001073RTCPSender::BuildREMB(uint8_t* rtcpbuffer, uint32_t& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001074{
1075 // sanity
1076 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1077 {
1078 return -2;
1079 }
1080 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001081 uint8_t FMT = 15;
1082 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1083 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001084
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001085 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001086 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1087
1088 // Add our own SSRC
1089 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1090 pos += 4;
1091
1092 // Remote SSRC must be 0
1093 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1094 pos += 4;
1095
1096 rtcpbuffer[pos++]='R';
1097 rtcpbuffer[pos++]='E';
1098 rtcpbuffer[pos++]='M';
1099 rtcpbuffer[pos++]='B';
1100
1101 rtcpbuffer[pos++] = _lengthRembSSRC;
1102 // 6 bit Exp
1103 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001104 uint8_t brExp = 0;
1105 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001106 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001107 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001108 {
1109 brExp = i;
1110 break;
1111 }
1112 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001113 const uint32_t brMantissa = (_rembBitrate >> brExp);
1114 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1115 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1116 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001117
1118 for (int i = 0; i < _lengthRembSSRC; i++)
1119 {
1120 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1121 pos += 4;
1122 }
1123 return 0;
1124}
1125
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001126void
1127RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001128{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001129 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001130 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001131}
1132
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001133int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001134RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001135{
1136 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1137 // If the sender is an owner of the TMMBN -> send TMMBR
1138 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1139
niklase@google.com470e71d2011-07-07 08:21:25 +00001140 // get current bounding set from RTCP receiver
1141 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001142 // store in candidateSet, allocates one extra slot
1143 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001144
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001145 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1146 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1147 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001148 int32_t lengthOfBoundingSet
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001149 = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001150
1151 if(lengthOfBoundingSet > 0)
1152 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001153 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001154 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001155 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1156 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001157 {
1158 // do not send the same tuple
1159 return 0;
1160 }
1161 }
1162 if(!tmmbrOwner)
1163 {
1164 // use received bounding set as candidate set
1165 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001166 candidateSet->SetEntry(lengthOfBoundingSet,
1167 _tmmbr_Send,
1168 _packetOH_Send,
1169 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001170 int numCandidates = lengthOfBoundingSet+ 1;
1171
1172 // find bounding set
1173 TMMBRSet* boundingSet = NULL;
1174 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1175 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1176 {
1177 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1178 }
1179 if(!tmmbrOwner)
1180 {
1181 // did not enter bounding set, no meaning to send this request
1182 return 0;
1183 }
1184 }
1185 }
1186
1187 if(_tmmbr_Send)
1188 {
1189 // sanity
1190 if(pos + 20 >= IP_PACKET_SIZE)
1191 {
1192 return -2;
1193 }
1194 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001195 uint8_t FMT = 3;
1196 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1197 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001198
1199 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001200 rtcpbuffer[pos++]=(uint8_t)0;
1201 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001202
1203 // Add our own SSRC
1204 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1205 pos += 4;
1206
1207 // RFC 5104 4.2.1.2. Semantics
1208
1209 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001210 rtcpbuffer[pos++]=(uint8_t)0;
1211 rtcpbuffer[pos++]=(uint8_t)0;
1212 rtcpbuffer[pos++]=(uint8_t)0;
1213 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001214
1215 // Additional Feedback Control Information (FCI)
1216 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1217 pos += 4;
1218
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001219 uint32_t bitRate = _tmmbr_Send*1000;
1220 uint32_t mmbrExp = 0;
1221 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001222 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001223 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001224 {
1225 mmbrExp = i;
1226 break;
1227 }
1228 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001229 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001230
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001231 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1232 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1233 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1234 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001235 }
1236 return 0;
1237}
1238
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001239int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001240RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001241{
1242 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1243 if(boundingSet == NULL)
1244 {
1245 return -1;
1246 }
1247 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001248 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001249 {
1250 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1251 return -2;
1252 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001253 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001254 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001255 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1256 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001257
1258 //Add length later
1259 int posLength = pos;
1260 pos++;
1261 pos++;
1262
1263 // Add our own SSRC
1264 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1265 pos += 4;
1266
1267 // RFC 5104 4.2.2.2. Semantics
1268
1269 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001270 rtcpbuffer[pos++]=(uint8_t)0;
1271 rtcpbuffer[pos++]=(uint8_t)0;
1272 rtcpbuffer[pos++]=(uint8_t)0;
1273 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001274
1275 // Additional Feedback Control Information (FCI)
1276 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001277 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001278 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001279 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001280 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001281 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001282 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1283 pos += 4;
1284
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001285 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1286 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001287 for(int i=0; i<64; i++)
1288 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001289 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001290 {
1291 mmbrExp = i;
1292 break;
1293 }
1294 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001295 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1296 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001297
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001298 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1299 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1300 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1301 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001302 numBoundingSet++;
1303 }
1304 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001305 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1306 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1307 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001308 return 0;
1309}
1310
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001311int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001312RTCPSender::BuildAPP(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001313{
1314 // sanity
1315 if(_appData == NULL)
1316 {
1317 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1318 return -1;
1319 }
1320 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1321 {
1322 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1323 return -2;
1324 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001325 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001326
1327 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001328 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001329
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001330 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1331 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1332 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001333
1334 // Add our own SSRC
1335 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1336 pos += 4;
1337
1338 // Add our application name
1339 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1340 pos += 4;
1341
1342 // Add the data
1343 memcpy(rtcpbuffer +pos, _appData,_appLength);
1344 pos += _appLength;
1345 return 0;
1346}
1347
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001348int32_t
1349RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001350 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001351 const int32_t nackSize,
1352 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001353 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001354{
1355 // sanity
1356 if(pos + 16 >= IP_PACKET_SIZE)
1357 {
1358 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1359 return -2;
1360 }
1361
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001362 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001363 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001364 uint8_t FMT = 1;
1365 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1366 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001367
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001368 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001369 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001370 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001371
1372 // Add our own SSRC
1373 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1374 pos += 4;
1375
1376 // Add the remote SSRC
1377 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1378 pos += 4;
1379
edjee@google.com79b02892013-04-04 19:43:34 +00001380 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001381 // Build NACK bitmasks and write them to the RTCP message.
1382 // The nack list should be sorted and not contain duplicates if one
1383 // wants to build the smallest rtcp nack packet.
1384 int numOfNackFields = 0;
1385 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1386 (IP_PACKET_SIZE - pos) / 4);
1387 int i = 0;
1388 while (i < nackSize && numOfNackFields < maxNackFields) {
1389 stringBuilder.PushNACK(nackList[i]);
1390 uint16_t nack = nackList[i++];
1391 uint16_t bitmask = 0;
1392 while (i < nackSize) {
1393 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1394 if (shift >= 0 && shift <= 15) {
1395 stringBuilder.PushNACK(nackList[i]);
1396 bitmask |= (1 << shift);
1397 ++i;
1398 } else {
1399 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001400 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001401 }
1402 // Write the sequence number and the bitmask to the packet.
1403 assert(pos + 4 < IP_PACKET_SIZE);
1404 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
1405 pos += 2;
1406 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
1407 pos += 2;
1408 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001409 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001410 if (i != nackSize) {
1411 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1412 "Nack list to large for one packet.");
1413 }
1414 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001415 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001416 return 0;
1417}
1418
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001419int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001420RTCPSender::BuildBYE(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001421{
1422 // sanity
1423 if(pos + 8 >= IP_PACKET_SIZE)
1424 {
1425 return -2;
1426 }
1427 if(_includeCSRCs)
1428 {
1429 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001430 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1431 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001432
1433 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001434 rtcpbuffer[pos++]=(uint8_t)0;
1435 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001436
1437 // Add our own SSRC
1438 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1439 pos += 4;
1440
1441 // add CSRCs
1442 for(int i = 0; i < _CSRCs; i++)
1443 {
1444 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1445 pos += 4;
1446 }
1447 } else
1448 {
1449 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001450 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1451 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001452
1453 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001454 rtcpbuffer[pos++]=(uint8_t)0;
1455 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001456
1457 // Add our own SSRC
1458 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1459 pos += 4;
1460 }
1461 return 0;
1462}
1463
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001464int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001465RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001466{
1467 // sanity
1468 if(pos + 44 >= IP_PACKET_SIZE)
1469 {
1470 return -2;
1471 }
1472
1473 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001474 rtcpbuffer[pos++]=(uint8_t)0x80;
1475 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001476
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001477 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001478
1479 // handle length later on
1480 pos++;
1481 pos++;
1482
1483 // Add our own SSRC
1484 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1485 pos += 4;
1486
1487 // Add a VoIP metrics block
1488 rtcpbuffer[pos++]=7;
1489 rtcpbuffer[pos++]=0;
1490 rtcpbuffer[pos++]=0;
1491 rtcpbuffer[pos++]=8;
1492
1493 // Add the remote SSRC
1494 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1495 pos += 4;
1496
1497 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1498 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1499 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1500 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1501
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001502 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1503 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1504 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1505 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001506
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001507 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1508 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1509 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1510 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001511
1512 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1513 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1514 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1515 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1516
1517 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1518 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1519 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1520 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1521
1522 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1523 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001524 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1525 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001526
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001527 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1528 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1529 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1530 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001531
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001532 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1533 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001534 return 0;
1535}
1536
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001537int32_t
tnakamura@webrtc.orgaa4d96a2013-07-16 19:25:04 +00001538RTCPSender::SendRTCP(const uint32_t packetTypeFlags,
1539 const int32_t nackSize, // NACK
1540 const uint16_t* nackList, // NACK
1541 const bool repeat, // FIR
1542 const uint64_t pictureID) // SLI & RPSI
niklase@google.com470e71d2011-07-07 08:21:25 +00001543{
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001544 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1545 uint32_t pos = 0;
1546 uint8_t rtcpbuffer[IP_PACKET_SIZE];
1547
1548 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 +00001549 {
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001550 // collect the received information
1551 RTCPReportBlock received;
1552 bool hasReceived = false;
1553 uint32_t NTPsec = 0;
1554 uint32_t NTPfrac = 0;
1555 bool rtcpCompound = false;
1556 uint32_t jitterTransmissionOffset = 0;
1557
1558 {
1559 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1560 if(_method == kRtcpOff)
1561 {
1562 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1563 "%s invalid state", __FUNCTION__);
1564 return -1;
1565 }
1566 rtcpCompound = (_method == kRtcpCompound) ? true : false;
1567 }
1568
1569 if (rtcpCompound ||
1570 rtcpPacketTypeFlags & kRtcpReport ||
1571 rtcpPacketTypeFlags & kRtcpSr ||
1572 rtcpPacketTypeFlags & kRtcpRr)
1573 {
tnakamura@webrtc.orgaa4d96a2013-07-16 19:25:04 +00001574 // get statistics from our RTPreceiver outside critsect
1575 if(_rtpRtcp.ReportBlockStatistics(&received.fractionLost,
1576 &received.cumulativeLost,
1577 &received.extendedHighSeqNum,
1578 &received.jitter,
1579 &jitterTransmissionOffset) == 0)
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001580 {
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001581 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