blob: a7c7dbc5ebdf198b1f9d38b5cfcf9f61d6512ac8 [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
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> // assert
14#include <stdlib.h> // rand
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000015#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000017#include <algorithm> // min
18
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000019#include "webrtc/common_types.h"
20#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
21#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
22#include "webrtc/system_wrappers/interface/trace.h"
23#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000024
niklase@google.com470e71d2011-07-07 08:21:25 +000025namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000026
27using RTCPUtility::RTCPCnameInformation;
28
edjee@google.com79b02892013-04-04 19:43:34 +000029NACKStringBuilder::NACKStringBuilder() :
30 _stream(""), _count(0), _consecutive(false)
31{
32 // Empty.
33}
34
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000035NACKStringBuilder::~NACKStringBuilder() {}
36
pbos@webrtc.org2f446732013-04-08 11:08:41 +000037void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000038{
39 if (_count == 0)
40 {
41 _stream << nack;
42 } else if (nack == _prevNack + 1)
43 {
44 _consecutive = true;
45 } else
46 {
47 if (_consecutive)
48 {
49 _stream << "-" << _prevNack;
50 _consecutive = false;
51 }
52 _stream << "," << nack;
53 }
54 _count++;
55 _prevNack = nack;
56}
57
58std::string NACKStringBuilder::GetResult()
59{
60 if (_consecutive)
61 {
62 _stream << "-" << _prevNack;
63 _consecutive = false;
64 }
65 return _stream.str();
66}
67
pbos@webrtc.org2f446732013-04-08 11:08:41 +000068RTCPSender::RTCPSender(const int32_t id,
niklase@google.com470e71d2011-07-07 08:21:25 +000069 const bool audio,
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000070 Clock* clock,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +000071 ModuleRtpRtcpImpl* owner) :
niklase@google.com470e71d2011-07-07 08:21:25 +000072 _id(id),
73 _audio(audio),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000074 _clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000075 _method(kRtcpOff),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000076 _rtpRtcp(*owner),
henrike@webrtc.org65573f22011-12-13 19:17:27 +000077 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000078 _cbTransport(NULL),
79
henrike@webrtc.org65573f22011-12-13 19:17:27 +000080 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000081 _usingNack(false),
82 _sending(false),
83 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000084 _REMB(false),
85 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000086 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +000087 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000088 _nextTimeToSendRTCP(0),
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000089 start_timestamp_(0),
90 last_rtp_timestamp_(0),
91 last_frame_capture_time_ms_(-1),
niklase@google.com470e71d2011-07-07 08:21:25 +000092 _SSRC(0),
93 _remoteSSRC(0),
94 _CNAME(),
elham@webrtc.orgb7eda432013-07-15 21:08:27 +000095 _reportBlocks(),
niklase@google.com470e71d2011-07-07 08:21:25 +000096 _csrcCNAMEs(),
97
stefan@webrtc.org7da34592013-04-09 14:56:29 +000098 _cameraDelayMS(0),
99
niklase@google.com470e71d2011-07-07 08:21:25 +0000100 _lastSendReport(),
101 _lastRTCPTime(),
102
103 _CSRCs(0),
104 _CSRC(),
105 _includeCSRCs(true),
106
107 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000108
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000109 _lengthRembSSRC(0),
110 _sizeRembSSRC(0),
111 _rembSSRC(NULL),
112 _rembBitrate(0),
113
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000114 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000115 _tmmbr_Send(0),
116 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000117
118 _appSend(false),
119 _appSubType(0),
120 _appName(),
121 _appData(NULL),
122 _appLength(0),
123 _xrSendVoIPMetric(false),
edjee@google.com79b02892013-04-04 19:43:34 +0000124 _xrVoIPMetric(),
125 _nackCount(0),
126 _pliCount(0),
127 _fullIntraRequestCount(0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000128{
129 memset(_CNAME, 0, sizeof(_CNAME));
130 memset(_lastSendReport, 0, sizeof(_lastSendReport));
131 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
132
133 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
134}
135
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000136RTCPSender::~RTCPSender() {
137 delete [] _rembSSRC;
138 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000139
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000140 while (!_reportBlocks.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000141 std::map<uint32_t, RTCPReportBlock*>::iterator it =
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000142 _reportBlocks.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000143 delete it->second;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000144 _reportBlocks.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000145 }
146 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000147 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000148 _csrcCNAMEs.begin();
149 delete it->second;
150 _csrcCNAMEs.erase(it);
151 }
152 delete _criticalSectionTransport;
153 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000154
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000155 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000156}
157
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000158int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000159RTCPSender::Init()
160{
161 CriticalSectionScoped lock(_criticalSectionRTCPSender);
162
163 _method = kRtcpOff;
164 _cbTransport = NULL;
165 _usingNack = false;
166 _sending = false;
167 _sendTMMBN = false;
168 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000169 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000170 _REMB = false;
171 _sendREMB = false;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000172 last_rtp_timestamp_ = 0;
173 last_frame_capture_time_ms_ = -1;
174 start_timestamp_ = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000175 _SSRC = 0;
176 _remoteSSRC = 0;
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000177 _cameraDelayMS = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000178 _sequenceNumberFIR = 0;
179 _tmmbr_Send = 0;
180 _packetOH_Send = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000181 _nextTimeToSendRTCP = 0;
182 _CSRCs = 0;
183 _appSend = false;
184 _appSubType = 0;
185
186 if(_appData)
187 {
188 delete [] _appData;
189 _appData = NULL;
190 }
191 _appLength = 0;
192
193 _xrSendVoIPMetric = false;
194
195 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
196 memset(_CNAME, 0, sizeof(_CNAME));
197 memset(_lastSendReport, 0, sizeof(_lastSendReport));
198 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
edjee@google.com79b02892013-04-04 19:43:34 +0000199
200 _nackCount = 0;
201 _pliCount = 0;
202 _fullIntraRequestCount = 0;
203
niklase@google.com470e71d2011-07-07 08:21:25 +0000204 return 0;
205}
206
207void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000208RTCPSender::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +0000209{
210 _id = id;
211}
212
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000213int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000214RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
215{
216 CriticalSectionScoped lock(_criticalSectionTransport);
217 _cbTransport = outgoingTransport;
218 return 0;
219}
220
221RTCPMethod
222RTCPSender::Status() const
223{
224 CriticalSectionScoped lock(_criticalSectionRTCPSender);
225 return _method;
226}
227
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000228int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000229RTCPSender::SetRTCPStatus(const RTCPMethod method)
230{
231 CriticalSectionScoped lock(_criticalSectionRTCPSender);
232 if(method != kRtcpOff)
233 {
234 if(_audio)
235 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000236 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000237 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000238 } else
239 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000240 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000241 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000242 }
243 }
244 _method = method;
245 return 0;
246}
247
248bool
249RTCPSender::Sending() const
250{
251 CriticalSectionScoped lock(_criticalSectionRTCPSender);
252 return _sending;
253}
254
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000255int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000256RTCPSender::SetSendingStatus(const bool sending)
257{
258 bool sendRTCPBye = false;
259 {
260 CriticalSectionScoped lock(_criticalSectionRTCPSender);
261
262 if(_method != kRtcpOff)
263 {
264 if(sending == false && _sending == true)
265 {
266 // Trigger RTCP bye
267 sendRTCPBye = true;
268 }
269 }
270 _sending = sending;
271 }
272 if(sendRTCPBye)
273 {
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000274 return SendRTCP(kRtcpBye, NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +0000275 }
276 return 0;
277}
278
279bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000280RTCPSender::REMB() const
281{
282 CriticalSectionScoped lock(_criticalSectionRTCPSender);
283 return _REMB;
284}
285
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000286int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000287RTCPSender::SetREMBStatus(const bool enable)
288{
289 CriticalSectionScoped lock(_criticalSectionRTCPSender);
290 _REMB = enable;
291 return 0;
292}
293
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000294int32_t
295RTCPSender::SetREMBData(const uint32_t bitrate,
296 const uint8_t numberOfSSRC,
297 const uint32_t* SSRC)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000298{
299 CriticalSectionScoped lock(_criticalSectionRTCPSender);
300 _rembBitrate = bitrate;
301
302 if(_sizeRembSSRC < numberOfSSRC)
303 {
304 delete [] _rembSSRC;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000305 _rembSSRC = new uint32_t[numberOfSSRC];
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000306 _sizeRembSSRC = numberOfSSRC;
307 }
308
309 _lengthRembSSRC = numberOfSSRC;
310 for (int i = 0; i < numberOfSSRC; i++)
311 {
312 _rembSSRC[i] = SSRC[i];
313 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000314 _sendREMB = true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000315 return 0;
316}
317
318bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000319RTCPSender::TMMBR() const
320{
321 CriticalSectionScoped lock(_criticalSectionRTCPSender);
322 return _TMMBR;
323}
324
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000325int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000326RTCPSender::SetTMMBRStatus(const bool enable)
327{
328 CriticalSectionScoped lock(_criticalSectionRTCPSender);
329 _TMMBR = enable;
330 return 0;
331}
332
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000333bool
334RTCPSender::IJ() const
335{
336 CriticalSectionScoped lock(_criticalSectionRTCPSender);
337 return _IJ;
338}
339
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000340int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000341RTCPSender::SetIJStatus(const bool enable)
342{
343 CriticalSectionScoped lock(_criticalSectionRTCPSender);
344 _IJ = enable;
345 return 0;
346}
347
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000348void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
349 start_timestamp_ = start_timestamp;
350}
351
352void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
353 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000354 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000355 last_rtp_timestamp_ = rtp_timestamp;
356 if (capture_time_ms < 0) {
357 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000358 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000359 } else {
360 last_frame_capture_time_ms_ = capture_time_ms;
361 }
362}
363
niklase@google.com470e71d2011-07-07 08:21:25 +0000364void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000365RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000366{
367 CriticalSectionScoped lock(_criticalSectionRTCPSender);
368
369 if(_SSRC != 0)
370 {
371 // not first SetSSRC, probably due to a collision
372 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000373 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000374 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000375 }
376 _SSRC = ssrc;
377}
378
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000379void RTCPSender::SetRemoteSSRC(uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000380{
381 CriticalSectionScoped lock(_criticalSectionRTCPSender);
382 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000383}
384
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000385int32_t
386RTCPSender::SetCameraDelay(const int32_t delayMS)
387{
388 CriticalSectionScoped lock(_criticalSectionRTCPSender);
389 if(delayMS > 1000 || delayMS < -1000)
390 {
391 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
392 return -1;
393 }
394 _cameraDelayMS = delayMS;
395 return 0;
396}
397
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000398int32_t RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000399 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000400 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000401 cName[RTCP_CNAME_SIZE - 1] = 0;
402 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000403 return 0;
404}
405
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000406int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000407 if (!cName)
408 return -1;
409
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000410 CriticalSectionScoped lock(_criticalSectionRTCPSender);
411 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
412 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
413 return 0;
414}
415
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000416int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
417 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000418 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000419 CriticalSectionScoped lock(_criticalSectionRTCPSender);
420 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
421 return -1;
422 }
423 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000424 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
425 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000426 _csrcCNAMEs[SSRC] = ptr;
427 return 0;
428}
429
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000430int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000431 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000432 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000433 _csrcCNAMEs.find(SSRC);
434
435 if (it == _csrcCNAMEs.end()) {
436 return -1;
437 }
438 delete it->second;
439 _csrcCNAMEs.erase(it);
440 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000441}
442
443bool
444RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
445{
446/*
447 For audio we use a fix 5 sec interval
448
449 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
450 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
451
452
453From RFC 3550
454
455 MAX RTCP BW is 5% if the session BW
456 A send report is approximately 65 bytes inc CNAME
457 A report report is approximately 28 bytes
458
459 The RECOMMENDED value for the reduced minimum in seconds is 360
460 divided by the session bandwidth in kilobits/second. This minimum
461 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
462
463 If the participant has not yet sent an RTCP packet (the variable
464 initial is true), the constant Tmin is set to 2.5 seconds, else it
465 is set to 5 seconds.
466
467 The interval between RTCP packets is varied randomly over the
468 range [0.5,1.5] times the calculated interval to avoid unintended
469 synchronization of all participants
470
471 if we send
472 If the participant is a sender (we_sent true), the constant C is
473 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
474 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
475 number of senders.
476
477 if we receive only
478 If we_sent is not true, the constant C is set
479 to the average RTCP packet size divided by 75% of the RTCP
480 bandwidth. The constant n is set to the number of receivers
481 (members - senders). If the number of senders is greater than
482 25%, senders and receivers are treated together.
483
484 reconsideration NOT required for peer-to-peer
485 "timer reconsideration" is
486 employed. This algorithm implements a simple back-off mechanism
487 which causes users to hold back RTCP packet transmission if the
488 group sizes are increasing.
489
490 n = number of members
491 C = avg_size/(rtcpBW/4)
492
493 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
494
495 4. The calculated interval T is set to a number uniformly distributed
496 between 0.5 and 1.5 times the deterministic calculated interval.
497
498 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
499 for the fact that the timer reconsideration algorithm converges to
500 a value of the RTCP bandwidth below the intended average
501*/
502
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000503 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000504
505 CriticalSectionScoped lock(_criticalSectionRTCPSender);
506
niklase@google.com470e71d2011-07-07 08:21:25 +0000507 if(_method == kRtcpOff)
508 {
509 return false;
510 }
511
niklase@google.com470e71d2011-07-07 08:21:25 +0000512 if(!_audio && sendKeyframeBeforeRTP)
513 {
514 // for video key-frames we want to send the RTCP before the large key-frame
515 // if we have a 100 ms margin
516 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
517 }
518
519 if(now > _nextTimeToSendRTCP)
520 {
521 return true;
522
523 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
524 {
525 // wrap
526 return true;
527 }
528 return false;
529}
530
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000531uint32_t
532RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000533{
534 CriticalSectionScoped lock(_criticalSectionRTCPSender);
535
536 lastRTCPTime = _lastRTCPTime[0];
537 return _lastSendReport[0];
538}
539
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000540uint32_t
541RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000542{
543 CriticalSectionScoped lock(_criticalSectionRTCPSender);
544
545 // This is only saved when we are the sender
546 if((_lastSendReport[0] == 0) || (sendReport == 0))
547 {
548 return 0; // will be ignored
549 } else
550 {
551 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
552 {
553 if( _lastSendReport[i] == sendReport)
554 {
555 return _lastRTCPTime[i];
556 }
557 }
558 }
559 return 0;
560}
561
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000562int32_t RTCPSender::AddReportBlock(const uint32_t SSRC,
563 const RTCPReportBlock* reportBlock) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000564 if (reportBlock == NULL) {
565 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
566 "%s invalid argument", __FUNCTION__);
567 return -1;
568 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000569 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000570
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000571 if (_reportBlocks.size() >= RTCP_MAX_REPORT_BLOCKS) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000572 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
573 "%s invalid argument", __FUNCTION__);
574 return -1;
575 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000576 std::map<uint32_t, RTCPReportBlock*>::iterator it =
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000577 _reportBlocks.find(SSRC);
578 if (it != _reportBlocks.end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000579 delete it->second;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000580 _reportBlocks.erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000581 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000582 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
583 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000584 _reportBlocks[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000585 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000586}
587
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000588int32_t RTCPSender::RemoveReportBlock(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000589 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000590
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000591 std::map<uint32_t, RTCPReportBlock*>::iterator it =
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000592 _reportBlocks.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000593
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000594 if (it == _reportBlocks.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000595 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000596 }
597 delete it->second;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000598 _reportBlocks.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000599 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000600}
601
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000602int32_t
603RTCPSender::BuildSR(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000604 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000605 const uint32_t NTPsec,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000606 const uint32_t NTPfrac,
607 const RTCPReportBlock* received)
niklase@google.com470e71d2011-07-07 08:21:25 +0000608{
609 // sanity
610 if(pos + 52 >= IP_PACKET_SIZE)
611 {
612 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
613 return -2;
614 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000615 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000616
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000617 uint32_t posNumberOfReportBlocks = pos;
618 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000619
620 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000621 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000622
623 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
624 {
625 // shift old
626 _lastSendReport[i+1] = _lastSendReport[i];
627 _lastRTCPTime[i+1] =_lastRTCPTime[i];
628 }
629
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000630 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000631 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000632
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000633 uint32_t freqHz = 90000; // For video
634 if(_audio) {
635 freqHz = _rtpRtcp.CurrentSendFrequencyHz();
niklase@google.com470e71d2011-07-07 08:21:25 +0000636 }
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000637
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000638 // The timestamp of this RTCP packet should be estimated as the timestamp of
639 // the frame being captured at this moment. We are calculating that
640 // timestamp as the last frame's timestamp + the time since the last frame
641 // was captured.
642 {
643 // Needs protection since this method is called on the process thread.
644 CriticalSectionScoped lock(_criticalSectionRTCPSender);
645 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
646 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
647 (freqHz / 1000);
648 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000649
650 // Add sender data
651 // Save for our length field
652 pos++;
653 pos++;
654
655 // Add our own SSRC
656 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
657 pos += 4;
658 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000659 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000660 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000661 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000662 pos += 4;
663 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
664 pos += 4;
665
666 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000667 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000668 pos += 4;
669
670 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000671 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000672 pos += 4;
673
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000674 uint8_t numberOfReportBlocks = 0;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000675 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000676 if(retVal < 0)
677 {
678 //
679 return retVal ;
680 }
681 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
682
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000683 uint16_t len = uint16_t((pos/4) -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000684 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
685 return 0;
686}
687
688
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000689int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000690 uint32_t& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000691 size_t lengthCname = strlen(_CNAME);
692 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000693
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000694 // sanity
695 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
696 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
697 "%s invalid argument", __FUNCTION__);
698 return -2;
699 }
700 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000701
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000702 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000703 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
704 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000705
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000706 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000707 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000708 pos++;
709 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000710
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000711 // Add our own SSRC
712 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
713 pos += 4;
714
715 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000716 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000717
718 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000719 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000720
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000721 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000722
723 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
724 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000725 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000726
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000727 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000728 // We must have a zero field even if we have an even multiple of 4 bytes
729 if ((pos % 4) == 0) {
730 padding++;
731 rtcpbuffer[pos++]=0;
732 }
733 while ((pos % 4) != 0) {
734 padding++;
735 rtcpbuffer[pos++]=0;
736 }
737 SDESLength += padding;
738
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000739 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000740 _csrcCNAMEs.begin();
741
742 for(; it != _csrcCNAMEs.end(); it++) {
743 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000744 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000745
746 // Add SSRC
747 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000748 pos += 4;
749
750 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000751 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000752
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000753 size_t length = strlen(cname->name);
754 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000755
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000756 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000757 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000758
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000759 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000760
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000761 pos += length;
762 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000763 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000764
765 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000766 if((pos % 4) == 0){
767 padding++;
768 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000769 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000770 while((pos % 4) != 0){
771 padding++;
772 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000773 }
774 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000775 }
776 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000777 uint16_t buffer_length = (SDESLength / 4) - 1;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000778 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
779 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000780 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000781}
782
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000783int32_t
784RTCPSender::BuildRR(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000785 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000786 const uint32_t NTPsec,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000787 const uint32_t NTPfrac,
788 const RTCPReportBlock* received)
niklase@google.com470e71d2011-07-07 08:21:25 +0000789{
790 // sanity one block
791 if(pos + 32 >= IP_PACKET_SIZE)
792 {
793 return -2;
794 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000795 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000796
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000797 rtcpbuffer[pos++]=(uint8_t)0x80;
798 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000799
800 // Save for our length field
801 pos++;
802 pos++;
803
804 // Add our own SSRC
805 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
806 pos += 4;
807
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000808 uint8_t numberOfReportBlocks = 0;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000809 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000810 if(retVal < 0)
811 {
812 return retVal;
813 }
814 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
815
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000816 uint16_t len = uint16_t((pos)/4 -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000817 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
818 return 0;
819}
820
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000821// From RFC 5450: Transmission Time Offsets in RTP Streams.
822// 0 1 2 3
823// 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
824// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
825// hdr |V=2|P| RC | PT=IJ=195 | length |
826// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
827// | inter-arrival jitter |
828// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
829// . .
830// . .
831// . .
832// | inter-arrival jitter |
833// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
834//
835// If present, this RTCP packet must be placed after a receiver report
836// (inside a compound RTCP packet), and MUST have the same value for RC
837// (reception report count) as the receiver report.
838
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000839int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000840RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000841 uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000842 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000843 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000844{
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000845 if (_reportBlocks.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000846 {
847 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
848 return 0;
849 }
850
851 // sanity
852 if(pos + 8 >= IP_PACKET_SIZE)
853 {
854 return -2;
855 }
856 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000857 uint8_t RC = 1;
858 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
859 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000860
861 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000862 rtcpbuffer[pos++]=(uint8_t)0;
863 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000864
865 // Add inter-arrival jitter
866 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
867 jitterTransmissionTimeOffset);
868 pos += 4;
869 return 0;
870}
871
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000872int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000873RTCPSender::BuildPLI(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000874{
875 // sanity
876 if(pos + 12 >= IP_PACKET_SIZE)
877 {
878 return -2;
879 }
880 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000881 uint8_t FMT = 1;
882 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
883 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000884
885 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000886 rtcpbuffer[pos++]=(uint8_t)0;
887 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000888
889 // Add our own SSRC
890 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
891 pos += 4;
892
893 // Add the remote SSRC
894 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
895 pos += 4;
896 return 0;
897}
898
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000899int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000900 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000901 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000902 // sanity
903 if(pos + 20 >= IP_PACKET_SIZE) {
904 return -2;
905 }
906 if (!repeat) {
907 _sequenceNumberFIR++; // do not increase if repetition
908 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000909
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000910 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000911 uint8_t FMT = 4;
912 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
913 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000914
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000915 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000916 rtcpbuffer[pos++] = (uint8_t)0;
917 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000918
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000919 // Add our own SSRC
920 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
921 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000922
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000923 // RFC 5104 4.3.1.2. Semantics
924 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000925 rtcpbuffer[pos++] = (uint8_t)0;
926 rtcpbuffer[pos++] = (uint8_t)0;
927 rtcpbuffer[pos++] = (uint8_t)0;
928 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000929
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000930 // Additional Feedback Control Information (FCI)
931 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
932 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000933
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000934 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
935 rtcpbuffer[pos++] = (uint8_t)0;
936 rtcpbuffer[pos++] = (uint8_t)0;
937 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000938 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000939}
940
941/*
942 0 1 2 3
943 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
944 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
945 | First | Number | PictureID |
946 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
947*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000948int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000949RTCPSender::BuildSLI(uint8_t* rtcpbuffer, uint32_t& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000950{
951 // sanity
952 if(pos + 16 >= IP_PACKET_SIZE)
953 {
954 return -2;
955 }
956 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000957 uint8_t FMT = 2;
958 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
959 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000960
961 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000962 rtcpbuffer[pos++]=(uint8_t)0;
963 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000964
965 // Add our own SSRC
966 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
967 pos += 4;
968
969 // Add the remote SSRC
970 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
971 pos += 4;
972
973 // Add first, number & picture ID 6 bits
974 // first = 0, 13 - bits
975 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000976 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000977 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
978 pos += 4;
979 return 0;
980}
981
982/*
983 0 1 2 3
984 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
985 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
986 | PB |0| Payload Type| Native RPSI bit string |
987 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
988 | defined per codec ... | Padding (0) |
989 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
990*/
991/*
992* Note: not generic made for VP8
993*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000994int32_t
995RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000996 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000997 const uint64_t pictureID,
998 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +0000999{
1000 // sanity
1001 if(pos + 24 >= IP_PACKET_SIZE)
1002 {
1003 return -2;
1004 }
1005 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001006 uint8_t FMT = 3;
1007 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1008 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001009
1010 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001011 uint32_t bitsRequired = 7;
1012 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001013 while((pictureID>>bitsRequired) > 0)
1014 {
1015 bitsRequired += 7;
1016 bytesRequired++;
1017 }
1018
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001019 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001020 if(bytesRequired > 6)
1021 {
1022 size = 5;
1023 } else if(bytesRequired > 2)
1024 {
1025 size = 4;
1026 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001027 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001028 rtcpbuffer[pos++]=size;
1029
1030 // Add our own SSRC
1031 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1032 pos += 4;
1033
1034 // Add the remote SSRC
1035 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1036 pos += 4;
1037
1038 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001039 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001040 if(paddingBytes == 4)
1041 {
1042 paddingBytes = 0;
1043 }
1044 // add padding length in bits
1045 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1046 pos++;
1047
1048 // add payload type
1049 rtcpbuffer[pos] = payloadType;
1050 pos++;
1051
1052 // add picture ID
1053 for(int i = bytesRequired-1; i > 0; i--)
1054 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001055 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001056 pos++;
1057 }
1058 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001059 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001060 pos++;
1061
1062 // add padding
1063 for(int j = 0; j <paddingBytes; j++)
1064 {
1065 rtcpbuffer[pos] = 0;
1066 pos++;
1067 }
1068 return 0;
1069}
1070
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001071int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001072RTCPSender::BuildREMB(uint8_t* rtcpbuffer, uint32_t& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001073{
1074 // sanity
1075 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1076 {
1077 return -2;
1078 }
1079 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001080 uint8_t FMT = 15;
1081 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1082 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001083
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001084 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001085 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1086
1087 // Add our own SSRC
1088 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1089 pos += 4;
1090
1091 // Remote SSRC must be 0
1092 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1093 pos += 4;
1094
1095 rtcpbuffer[pos++]='R';
1096 rtcpbuffer[pos++]='E';
1097 rtcpbuffer[pos++]='M';
1098 rtcpbuffer[pos++]='B';
1099
1100 rtcpbuffer[pos++] = _lengthRembSSRC;
1101 // 6 bit Exp
1102 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001103 uint8_t brExp = 0;
1104 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001105 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001106 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001107 {
1108 brExp = i;
1109 break;
1110 }
1111 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001112 const uint32_t brMantissa = (_rembBitrate >> brExp);
1113 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1114 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1115 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001116
1117 for (int i = 0; i < _lengthRembSSRC; i++)
1118 {
1119 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1120 pos += 4;
1121 }
1122 return 0;
1123}
1124
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001125void
1126RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001127{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001128 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001129 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001130}
1131
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001132int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001133RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001134{
1135 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1136 // If the sender is an owner of the TMMBN -> send TMMBR
1137 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1138
niklase@google.com470e71d2011-07-07 08:21:25 +00001139 // get current bounding set from RTCP receiver
1140 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001141 // store in candidateSet, allocates one extra slot
1142 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001143
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001144 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1145 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1146 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001147 int32_t lengthOfBoundingSet
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001148 = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001149
1150 if(lengthOfBoundingSet > 0)
1151 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001152 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001153 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001154 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1155 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001156 {
1157 // do not send the same tuple
1158 return 0;
1159 }
1160 }
1161 if(!tmmbrOwner)
1162 {
1163 // use received bounding set as candidate set
1164 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001165 candidateSet->SetEntry(lengthOfBoundingSet,
1166 _tmmbr_Send,
1167 _packetOH_Send,
1168 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001169 int numCandidates = lengthOfBoundingSet+ 1;
1170
1171 // find bounding set
1172 TMMBRSet* boundingSet = NULL;
1173 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1174 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1175 {
1176 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1177 }
1178 if(!tmmbrOwner)
1179 {
1180 // did not enter bounding set, no meaning to send this request
1181 return 0;
1182 }
1183 }
1184 }
1185
1186 if(_tmmbr_Send)
1187 {
1188 // sanity
1189 if(pos + 20 >= IP_PACKET_SIZE)
1190 {
1191 return -2;
1192 }
1193 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001194 uint8_t FMT = 3;
1195 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1196 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001197
1198 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001199 rtcpbuffer[pos++]=(uint8_t)0;
1200 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001201
1202 // Add our own SSRC
1203 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1204 pos += 4;
1205
1206 // RFC 5104 4.2.1.2. Semantics
1207
1208 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001209 rtcpbuffer[pos++]=(uint8_t)0;
1210 rtcpbuffer[pos++]=(uint8_t)0;
1211 rtcpbuffer[pos++]=(uint8_t)0;
1212 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001213
1214 // Additional Feedback Control Information (FCI)
1215 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1216 pos += 4;
1217
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001218 uint32_t bitRate = _tmmbr_Send*1000;
1219 uint32_t mmbrExp = 0;
1220 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001221 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001222 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001223 {
1224 mmbrExp = i;
1225 break;
1226 }
1227 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001228 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001229
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001230 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1231 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1232 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1233 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001234 }
1235 return 0;
1236}
1237
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001238int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001239RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001240{
1241 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1242 if(boundingSet == NULL)
1243 {
1244 return -1;
1245 }
1246 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001247 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001248 {
1249 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1250 return -2;
1251 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001252 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001253 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001254 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1255 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001256
1257 //Add length later
1258 int posLength = pos;
1259 pos++;
1260 pos++;
1261
1262 // Add our own SSRC
1263 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1264 pos += 4;
1265
1266 // RFC 5104 4.2.2.2. Semantics
1267
1268 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001269 rtcpbuffer[pos++]=(uint8_t)0;
1270 rtcpbuffer[pos++]=(uint8_t)0;
1271 rtcpbuffer[pos++]=(uint8_t)0;
1272 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001273
1274 // Additional Feedback Control Information (FCI)
1275 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001276 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001277 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001278 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001279 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001280 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001281 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1282 pos += 4;
1283
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001284 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1285 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001286 for(int i=0; i<64; i++)
1287 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001288 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001289 {
1290 mmbrExp = i;
1291 break;
1292 }
1293 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001294 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1295 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001296
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001297 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1298 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1299 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1300 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001301 numBoundingSet++;
1302 }
1303 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001304 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1305 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1306 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001307 return 0;
1308}
1309
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001310int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001311RTCPSender::BuildAPP(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001312{
1313 // sanity
1314 if(_appData == NULL)
1315 {
1316 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1317 return -1;
1318 }
1319 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1320 {
1321 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1322 return -2;
1323 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001324 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001325
1326 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001327 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001328
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001329 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1330 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1331 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001332
1333 // Add our own SSRC
1334 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1335 pos += 4;
1336
1337 // Add our application name
1338 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1339 pos += 4;
1340
1341 // Add the data
1342 memcpy(rtcpbuffer +pos, _appData,_appLength);
1343 pos += _appLength;
1344 return 0;
1345}
1346
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001347int32_t
1348RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001349 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001350 const int32_t nackSize,
1351 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001352 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001353{
1354 // sanity
1355 if(pos + 16 >= IP_PACKET_SIZE)
1356 {
1357 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1358 return -2;
1359 }
1360
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001361 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001362 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001363 uint8_t FMT = 1;
1364 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1365 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001366
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001367 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001368 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001369 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001370
1371 // Add our own SSRC
1372 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1373 pos += 4;
1374
1375 // Add the remote SSRC
1376 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1377 pos += 4;
1378
edjee@google.com79b02892013-04-04 19:43:34 +00001379 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001380 // Build NACK bitmasks and write them to the RTCP message.
1381 // The nack list should be sorted and not contain duplicates if one
1382 // wants to build the smallest rtcp nack packet.
1383 int numOfNackFields = 0;
1384 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1385 (IP_PACKET_SIZE - pos) / 4);
1386 int i = 0;
1387 while (i < nackSize && numOfNackFields < maxNackFields) {
1388 stringBuilder.PushNACK(nackList[i]);
1389 uint16_t nack = nackList[i++];
1390 uint16_t bitmask = 0;
1391 while (i < nackSize) {
1392 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1393 if (shift >= 0 && shift <= 15) {
1394 stringBuilder.PushNACK(nackList[i]);
1395 bitmask |= (1 << shift);
1396 ++i;
1397 } else {
1398 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001399 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001400 }
1401 // Write the sequence number and the bitmask to the packet.
1402 assert(pos + 4 < IP_PACKET_SIZE);
1403 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
1404 pos += 2;
1405 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
1406 pos += 2;
1407 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001408 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001409 if (i != nackSize) {
1410 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1411 "Nack list to large for one packet.");
1412 }
1413 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001414 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001415 return 0;
1416}
1417
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001418int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001419RTCPSender::BuildBYE(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001420{
1421 // sanity
1422 if(pos + 8 >= IP_PACKET_SIZE)
1423 {
1424 return -2;
1425 }
1426 if(_includeCSRCs)
1427 {
1428 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001429 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1430 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001431
1432 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001433 rtcpbuffer[pos++]=(uint8_t)0;
1434 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001435
1436 // Add our own SSRC
1437 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1438 pos += 4;
1439
1440 // add CSRCs
1441 for(int i = 0; i < _CSRCs; i++)
1442 {
1443 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1444 pos += 4;
1445 }
1446 } else
1447 {
1448 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001449 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1450 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001451
1452 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001453 rtcpbuffer[pos++]=(uint8_t)0;
1454 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001455
1456 // Add our own SSRC
1457 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1458 pos += 4;
1459 }
1460 return 0;
1461}
1462
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001463int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001464RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001465{
1466 // sanity
1467 if(pos + 44 >= IP_PACKET_SIZE)
1468 {
1469 return -2;
1470 }
1471
1472 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001473 rtcpbuffer[pos++]=(uint8_t)0x80;
1474 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001475
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001476 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001477
1478 // handle length later on
1479 pos++;
1480 pos++;
1481
1482 // Add our own SSRC
1483 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1484 pos += 4;
1485
1486 // Add a VoIP metrics block
1487 rtcpbuffer[pos++]=7;
1488 rtcpbuffer[pos++]=0;
1489 rtcpbuffer[pos++]=0;
1490 rtcpbuffer[pos++]=8;
1491
1492 // Add the remote SSRC
1493 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1494 pos += 4;
1495
1496 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1497 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1498 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1499 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1500
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001501 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1502 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1503 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1504 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001505
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001506 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1507 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1508 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1509 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001510
1511 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1512 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1513 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1514 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1515
1516 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1517 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1518 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1519 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1520
1521 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1522 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001523 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1524 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001525
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001526 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1527 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1528 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1529 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001530
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001531 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1532 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001533 return 0;
1534}
1535
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001536int32_t
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001537RTCPSender::SendRTCP(
1538 uint32_t packetTypeFlags,
1539 const ReceiveStatistics::RtpReceiveStatistics* receive_stats,
1540 int32_t nackSize,
1541 const uint16_t* nackList,
1542 bool repeat,
1543 uint64_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +00001544{
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001545 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1546 uint32_t pos = 0;
1547 uint8_t rtcpbuffer[IP_PACKET_SIZE];
1548
1549 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 +00001550 {
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001551 // collect the received information
1552 RTCPReportBlock received;
1553 bool hasReceived = false;
1554 uint32_t NTPsec = 0;
1555 uint32_t NTPfrac = 0;
1556 bool rtcpCompound = false;
1557 uint32_t jitterTransmissionOffset = 0;
1558
1559 {
1560 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1561 if(_method == kRtcpOff)
1562 {
1563 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1564 "%s invalid state", __FUNCTION__);
1565 return -1;
1566 }
1567 rtcpCompound = (_method == kRtcpCompound) ? true : false;
1568 }
1569
1570 if (rtcpCompound ||
1571 rtcpPacketTypeFlags & kRtcpReport ||
1572 rtcpPacketTypeFlags & kRtcpSr ||
1573 rtcpPacketTypeFlags & kRtcpRr)
1574 {
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001575 // Do we have receive statistics to send?
1576 if (receive_stats)
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001577 {
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001578 received.fractionLost = receive_stats->fraction_lost;
1579 received.cumulativeLost = receive_stats->cumulative_lost;
1580 received.extendedHighSeqNum =
1581 receive_stats->extended_max_sequence_number;
1582 received.jitter = receive_stats->jitter;
1583 jitterTransmissionOffset = 0;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001584 hasReceived = true;
1585
1586 uint32_t lastReceivedRRNTPsecs = 0;
1587 uint32_t lastReceivedRRNTPfrac = 0;
1588 uint32_t remoteSR = 0;
1589
1590 // ok even if we have not received a SR, we will send 0 in that case
1591 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1592 lastReceivedRRNTPfrac,
1593 remoteSR);
1594
1595 // get our NTP as late as possible to avoid a race
1596 _clock->CurrentNtp(NTPsec, NTPfrac);
1597
1598 // Delay since last received report
1599 uint32_t delaySinceLastReceivedSR = 0;
1600 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
1601 {
1602 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1603 uint32_t now=NTPsec&0x0000FFFF;
1604 now <<=16;
1605 now += (NTPfrac&0xffff0000)>>16;
1606
1607 uint32_t receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
1608 receiveTime <<=16;
1609 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1610
1611 delaySinceLastReceivedSR = now-receiveTime;
1612 }
1613 received.delaySinceLastSR = delaySinceLastReceivedSR;
1614 received.lastSR = remoteSR;
1615 } else
1616 {
1617 // we need to send our NTP even if we dont have received any reports
1618 _clock->CurrentNtp(NTPsec, NTPfrac);
1619 }
1620 }
1621
1622 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1623
1624 if(_TMMBR ) // attach TMMBR to send and receive reports
1625 {
1626 rtcpPacketTypeFlags |= kRtcpTmmbr;
1627 }
1628 if(_appSend)
1629 {
1630 rtcpPacketTypeFlags |= kRtcpApp;
1631 _appSend = false;
1632 }
1633 if(_REMB && _sendREMB)
1634 {
1635 // Always attach REMB to SR if that is configured. Note that REMB is
1636 // only sent on one of the RTP modules in the REMB group.
1637 rtcpPacketTypeFlags |= kRtcpRemb;
1638 }
1639 if(_xrSendVoIPMetric)
1640 {
1641 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1642 _xrSendVoIPMetric = false;
1643 }
1644 if(_sendTMMBN) // set when having received a TMMBR
1645 {
1646 rtcpPacketTypeFlags |= kRtcpTmmbn;
1647 _sendTMMBN = false;
1648 }
1649
1650 if(_method == kRtcpCompound)
1651 {
1652 if(_sending)
1653 {
1654 rtcpPacketTypeFlags |= kRtcpSr;
1655 } else
1656 {
1657 rtcpPacketTypeFlags |= kRtcpRr;
1658 }
1659 if (_IJ && hasReceived)
1660 {
1661 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1662 }
1663 } else if(_method == kRtcpNonCompound)
1664 {
1665 if(rtcpPacketTypeFlags & kRtcpReport)
1666 {
1667 if(_sending)
1668 {
1669 rtcpPacketTypeFlags |= kRtcpSr;
1670 } else
1671 {
1672 rtcpPacketTypeFlags |= kRtcpRr;
1673 }
1674 }
1675 }
1676 if( rtcpPacketTypeFlags & kRtcpRr ||
1677 rtcpPacketTypeFlags & kRtcpSr)
1678 {
1679 // generate next time to send a RTCP report
1680 // seeded from RTP constructor
1681 int32_t random = rand() % 1000;
1682 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1683
1684 if(_audio)
1685 {
1686 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
1687 }else
1688 {
1689 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1690 if(_sending)
1691 {
1692 // calc bw for video 360/sendBW in kbit/s
1693 uint32_t sendBitrateKbit = 0;
1694 uint32_t videoRate = 0;
1695 uint32_t fecRate = 0;
1696 uint32_t nackRate = 0;
1697 _rtpRtcp.BitrateSent(&sendBitrateKbit,
1698 &videoRate,
1699 &fecRate,
1700 &nackRate);
1701 sendBitrateKbit /= 1000;
1702 if(sendBitrateKbit != 0)
1703 {
1704 minIntervalMs = 360000/sendBitrateKbit;
1705 }
1706 }
1707 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1708 {
1709 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1710 }
1711 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1712 }
1713 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1714 }
1715
1716 // if the data does not fitt in the packet we fill it as much as possible
1717 int32_t buildVal = 0;
1718
1719 if(rtcpPacketTypeFlags & kRtcpSr)
1720 {
1721 if(hasReceived)
1722 {
1723 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
1724 } else
1725 {
1726 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac);
1727 }
1728 if(buildVal == -1)
1729 {
1730 return -1; // error
1731
1732 }else if(buildVal == -2)
1733 {
1734 break; // out of buffer
1735 }
1736 buildVal = BuildSDEC(rtcpbuffer, pos);
1737 if(buildVal == -1)
1738 {
1739 return -1; // error
1740
1741 }else if(buildVal == -2)
1742 {
1743 break; // out of buffer
1744 }
1745
1746 }else if(rtcpPacketTypeFlags & kRtcpRr)
1747 {
1748 if(hasReceived)
1749 {
1750 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
1751 }else
1752 {
1753 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
1754 }
1755 if(buildVal == -1)
1756 {
1757 return -1; // error
1758
1759 }else if(buildVal == -2)
1760 {
1761 break; // out of buffer
1762 }
1763 // only of set
1764 if(_CNAME[0] != 0)
1765 {
1766 buildVal = BuildSDEC(rtcpbuffer, pos);
1767 if(buildVal == -1)
1768 {
1769 return -1; // error
1770 }
1771 }
1772 }
1773 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1774 {
1775 // If present, this RTCP packet must be placed after a
1776 // receiver report.
1777 buildVal = BuildExtendedJitterReport(rtcpbuffer,
1778 pos,
1779 jitterTransmissionOffset);
1780 if(buildVal == -1)
1781 {
1782 return -1; // error
1783 }
1784 else if(buildVal == -2)
1785 {
1786 break; // out of buffer
1787 }
1788 }
1789 if(rtcpPacketTypeFlags & kRtcpPli)
1790 {
1791 buildVal = BuildPLI(rtcpbuffer, pos);
1792 if(buildVal == -1)
1793 {
1794 return -1; // error
1795
1796 }else if(buildVal == -2)
1797 {
1798 break; // out of buffer
1799 }
1800 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
1801 _pliCount++;
1802 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC, _pliCount);
1803 }
1804 if(rtcpPacketTypeFlags & kRtcpFir)
1805 {
1806 buildVal = BuildFIR(rtcpbuffer, pos, repeat);
1807 if(buildVal == -1)
1808 {
1809 return -1; // error
1810
1811 }else if(buildVal == -2)
1812 {
1813 break; // out of buffer
1814 }
1815 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
1816 _fullIntraRequestCount++;
1817 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
1818 _fullIntraRequestCount);
1819 }
1820 if(rtcpPacketTypeFlags & kRtcpSli)
1821 {
1822 buildVal = BuildSLI(rtcpbuffer, pos, (uint8_t)pictureID);
1823 if(buildVal == -1)
1824 {
1825 return -1; // error
1826
1827 }else if(buildVal == -2)
1828 {
1829 break; // out of buffer
1830 }
1831 }
1832 if(rtcpPacketTypeFlags & kRtcpRpsi)
1833 {
1834 const int8_t payloadType = _rtpRtcp.SendPayloadType();
1835 if(payloadType == -1)
1836 {
1837 return -1;
1838 }
1839 buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (uint8_t)payloadType);
1840 if(buildVal == -1)
1841 {
1842 return -1; // error
1843
1844 }else if(buildVal == -2)
1845 {
1846 break; // out of buffer
1847 }
1848 }
1849 if(rtcpPacketTypeFlags & kRtcpRemb)
1850 {
1851 buildVal = BuildREMB(rtcpbuffer, pos);
1852 if(buildVal == -1)
1853 {
1854 return -1; // error
1855
1856 }else if(buildVal == -2)
1857 {
1858 break; // out of buffer
1859 }
1860 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1861 }
1862 if(rtcpPacketTypeFlags & kRtcpBye)
1863 {
1864 buildVal = BuildBYE(rtcpbuffer, pos);
1865 if(buildVal == -1)
1866 {
1867 return -1; // error
1868
1869 }else if(buildVal == -2)
1870 {
1871 break; // out of buffer
1872 }
1873 }
1874 if(rtcpPacketTypeFlags & kRtcpApp)
1875 {
1876 buildVal = BuildAPP(rtcpbuffer, pos);
1877 if(buildVal == -1)
1878 {
1879 return -1; // error
1880
1881 }else if(buildVal == -2)
1882 {
1883 break; // out of buffer
1884 }
1885 }
1886 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1887 {
1888 buildVal = BuildTMMBR(rtcpbuffer, pos);
1889 if(buildVal == -1)
1890 {
1891 return -1; // error
1892
1893 }else if(buildVal == -2)
1894 {
1895 break; // out of buffer
1896 }
1897 }
1898 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1899 {
1900 buildVal = BuildTMMBN(rtcpbuffer, pos);
1901 if(buildVal == -1)
1902 {
1903 return -1; // error
1904
1905 }else if(buildVal == -2)
1906 {
1907 break; // out of buffer
1908 }
1909 }
1910 if(rtcpPacketTypeFlags & kRtcpNack)
1911 {
1912 std::string nackString;
1913 buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList,
1914 &nackString);
1915 if(buildVal == -1)
1916 {
1917 return -1; // error
1918
1919 }else if(buildVal == -2)
1920 {
1921 break; // out of buffer
1922 }
1923 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
1924 "nacks", TRACE_STR_COPY(nackString.c_str()));
1925 _nackCount++;
1926 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC, _nackCount);
1927 }
1928 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1929 {
1930 buildVal = BuildVoIPMetric(rtcpbuffer, pos);
1931 if(buildVal == -1)
1932 {
1933 return -1; // error
1934
1935 }else if(buildVal == -2)
1936 {
1937 break; // out of buffer
1938 }
1939 }
1940 }while (false);
1941 // Sanity don't send empty packets.
1942 if (pos == 0)
1943 {
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001944 return -1;
1945 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001946 return SendToNetwork(rtcpbuffer, (uint16_t)pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001947}
1948
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001949int32_t
1950RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
1951 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001952{
1953 CriticalSectionScoped lock(_criticalSectionTransport);
1954 if(_cbTransport)
1955 {
1956 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1957 {
1958 return 0;
1959 }
1960 }
1961 return -1;
1962}
1963
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001964int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00001965RTCPSender::SetCSRCStatus(const bool include)
1966{
1967 _includeCSRCs = include;
1968 return 0;
1969}
1970
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001971int32_t
1972RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
1973 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00001974{
1975 if(arrLength > kRtpCsrcSize)
1976 {
1977 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1978 assert(false);
1979 return -1;
1980 }
1981
1982 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1983
1984 for(int i = 0; i < arrLength;i++)
1985 {
1986 _CSRC[i] = arrOfCSRC[i];
1987 }
1988 _CSRCs = arrLength;
1989 return 0;
1990}
1991
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001992int32_t
1993RTCPSender::SetApplicationSpecificData(const uint8_t subType,
1994 const uint32_t name,
1995 const uint8_t* data,
1996 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001997{
1998 if(length %4 != 0)
1999 {
2000 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2001 return -1;
2002 }
2003 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2004
2005 if(_appData)
2006 {
2007 delete [] _appData;
2008 }
2009
2010 _appSend = true;
2011 _appSubType = subType;
2012 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002013 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002014 _appLength = length;
2015 memcpy(_appData, data, length);
2016 return 0;
2017}
2018
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002019int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002020RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2021{
2022 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2023 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2024
2025 _xrSendVoIPMetric = true;
2026 return 0;
2027}
2028
2029// called under critsect _criticalSectionRTCPSender
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002030int32_t RTCPSender::AddReportBlocks(uint8_t* rtcpbuffer,
2031 uint32_t& pos,
2032 uint8_t& numberOfReportBlocks,
2033 const RTCPReportBlock* received,
2034 const uint32_t NTPsec,
2035 const uint32_t NTPfrac) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002036 // sanity one block
2037 if(pos + 24 >= IP_PACKET_SIZE) {
2038 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2039 "%s invalid argument", __FUNCTION__);
2040 return -1;
2041 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002042 numberOfReportBlocks = _reportBlocks.size();
2043 if (received) {
2044 // add our multiple RR to numberOfReportBlocks
2045 numberOfReportBlocks++;
2046 }
2047 if (received) {
2048 // answer to the one that sends to me
2049 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
2050
2051 // Remote SSRC
2052 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
2053 pos += 4;
2054
2055 // fraction lost
2056 rtcpbuffer[pos++]=received->fractionLost;
2057
2058 // cumulative loss
2059 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2060 received->cumulativeLost);
2061 pos += 3;
2062 // extended highest seq_no, contain the highest sequence number received
2063 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2064 received->extendedHighSeqNum);
2065 pos += 4;
2066
2067 //Jitter
2068 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
2069 pos += 4;
2070
2071 // Last SR timestamp, our NTP time when we received the last report
2072 // This is the value that we read from the send report packet not when we
2073 // received it...
2074 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
2075 pos += 4;
2076
2077 // Delay since last received report,time since we received the report
2078 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2079 received->delaySinceLastSR);
2080 pos += 4;
2081 }
2082 if ((pos + _reportBlocks.size() * 24) >= IP_PACKET_SIZE) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002083 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2084 "%s invalid argument", __FUNCTION__);
2085 return -1;
2086 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002087 std::map<uint32_t, RTCPReportBlock*>::iterator it =
2088 _reportBlocks.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002089
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002090 for (; it != _reportBlocks.end(); it++) {
2091 // we can have multiple report block in a conference
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002092 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002093 RTCPReportBlock* reportBlock = it->second;
2094 if (reportBlock) {
2095 // Remote SSRC
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002096 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
2097 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002098
2099 // fraction lost
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002100 rtcpbuffer[pos++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002101
2102 // cumulative loss
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002103 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002104 reportBlock->cumulativeLost);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002105 pos += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002106
2107 // extended highest seq_no, contain the highest sequence number received
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002108 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002109 reportBlock->extendedHighSeqNum);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002110 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002111
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002112 //Jitter
2113 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002114 reportBlock->jitter);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002115 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002116
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002117 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002118 reportBlock->lastSR);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002119 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002120
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002121 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002122 reportBlock->delaySinceLastSR);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002123 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002124 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002125 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002126 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00002127}
2128
2129// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002130int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002131RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002132 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002133{
2134 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2135
2136 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2137 {
2138 _sendTMMBN = true;
2139 return 0;
2140 }
2141 return -1;
2142}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002143} // namespace webrtc