blob: 78f178900c9de06698eba31971fecfe5f08928c3 [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 {
tnakamura@webrtc.orgaa4d96a2013-07-16 19:25:04 +0000274 return SendRTCP(kRtcpBye);
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
tnakamura@webrtc.orgaa4d96a2013-07-16 19:25:04 +0000379int32_t
380RTCPSender::SetRemoteSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000381{
382 CriticalSectionScoped lock(_criticalSectionRTCPSender);
383 _remoteSSRC = ssrc;
tnakamura@webrtc.orgaa4d96a2013-07-16 19:25:04 +0000384 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000385}
386
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000387int32_t
388RTCPSender::SetCameraDelay(const int32_t delayMS)
389{
390 CriticalSectionScoped lock(_criticalSectionRTCPSender);
391 if(delayMS > 1000 || delayMS < -1000)
392 {
393 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
394 return -1;
395 }
396 _cameraDelayMS = delayMS;
397 return 0;
398}
399
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000400int32_t RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000401 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000402 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000403 cName[RTCP_CNAME_SIZE - 1] = 0;
404 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000405 return 0;
406}
407
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000408int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000409 if (!cName)
410 return -1;
411
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000412 CriticalSectionScoped lock(_criticalSectionRTCPSender);
413 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
414 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
415 return 0;
416}
417
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000418int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
419 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000420 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000421 CriticalSectionScoped lock(_criticalSectionRTCPSender);
422 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
423 return -1;
424 }
425 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000426 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
427 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000428 _csrcCNAMEs[SSRC] = ptr;
429 return 0;
430}
431
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000432int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000433 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000434 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000435 _csrcCNAMEs.find(SSRC);
436
437 if (it == _csrcCNAMEs.end()) {
438 return -1;
439 }
440 delete it->second;
441 _csrcCNAMEs.erase(it);
442 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000443}
444
445bool
446RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
447{
448/*
449 For audio we use a fix 5 sec interval
450
451 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
452 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
453
454
455From RFC 3550
456
457 MAX RTCP BW is 5% if the session BW
458 A send report is approximately 65 bytes inc CNAME
459 A report report is approximately 28 bytes
460
461 The RECOMMENDED value for the reduced minimum in seconds is 360
462 divided by the session bandwidth in kilobits/second. This minimum
463 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
464
465 If the participant has not yet sent an RTCP packet (the variable
466 initial is true), the constant Tmin is set to 2.5 seconds, else it
467 is set to 5 seconds.
468
469 The interval between RTCP packets is varied randomly over the
470 range [0.5,1.5] times the calculated interval to avoid unintended
471 synchronization of all participants
472
473 if we send
474 If the participant is a sender (we_sent true), the constant C is
475 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
476 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
477 number of senders.
478
479 if we receive only
480 If we_sent is not true, the constant C is set
481 to the average RTCP packet size divided by 75% of the RTCP
482 bandwidth. The constant n is set to the number of receivers
483 (members - senders). If the number of senders is greater than
484 25%, senders and receivers are treated together.
485
486 reconsideration NOT required for peer-to-peer
487 "timer reconsideration" is
488 employed. This algorithm implements a simple back-off mechanism
489 which causes users to hold back RTCP packet transmission if the
490 group sizes are increasing.
491
492 n = number of members
493 C = avg_size/(rtcpBW/4)
494
495 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
496
497 4. The calculated interval T is set to a number uniformly distributed
498 between 0.5 and 1.5 times the deterministic calculated interval.
499
500 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
501 for the fact that the timer reconsideration algorithm converges to
502 a value of the RTCP bandwidth below the intended average
503*/
504
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000505 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000506
507 CriticalSectionScoped lock(_criticalSectionRTCPSender);
508
niklase@google.com470e71d2011-07-07 08:21:25 +0000509 if(_method == kRtcpOff)
510 {
511 return false;
512 }
513
niklase@google.com470e71d2011-07-07 08:21:25 +0000514 if(!_audio && sendKeyframeBeforeRTP)
515 {
516 // for video key-frames we want to send the RTCP before the large key-frame
517 // if we have a 100 ms margin
518 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
519 }
520
521 if(now > _nextTimeToSendRTCP)
522 {
523 return true;
524
525 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
526 {
527 // wrap
528 return true;
529 }
530 return false;
531}
532
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000533uint32_t
534RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000535{
536 CriticalSectionScoped lock(_criticalSectionRTCPSender);
537
538 lastRTCPTime = _lastRTCPTime[0];
539 return _lastSendReport[0];
540}
541
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000542uint32_t
543RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000544{
545 CriticalSectionScoped lock(_criticalSectionRTCPSender);
546
547 // This is only saved when we are the sender
548 if((_lastSendReport[0] == 0) || (sendReport == 0))
549 {
550 return 0; // will be ignored
551 } else
552 {
553 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
554 {
555 if( _lastSendReport[i] == sendReport)
556 {
557 return _lastRTCPTime[i];
558 }
559 }
560 }
561 return 0;
562}
563
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000564int32_t RTCPSender::AddReportBlock(const uint32_t SSRC,
565 const RTCPReportBlock* reportBlock) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000566 if (reportBlock == NULL) {
567 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
568 "%s invalid argument", __FUNCTION__);
569 return -1;
570 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000571 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000572
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000573 if (_reportBlocks.size() >= RTCP_MAX_REPORT_BLOCKS) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000574 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
575 "%s invalid argument", __FUNCTION__);
576 return -1;
577 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000578 std::map<uint32_t, RTCPReportBlock*>::iterator it =
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000579 _reportBlocks.find(SSRC);
580 if (it != _reportBlocks.end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000581 delete it->second;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000582 _reportBlocks.erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000583 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000584 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
585 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000586 _reportBlocks[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000587 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000588}
589
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000590int32_t RTCPSender::RemoveReportBlock(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000591 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000592
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000593 std::map<uint32_t, RTCPReportBlock*>::iterator it =
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000594 _reportBlocks.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000595
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000596 if (it == _reportBlocks.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000597 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000598 }
599 delete it->second;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000600 _reportBlocks.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000601 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000602}
603
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000604int32_t
605RTCPSender::BuildSR(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000606 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000607 const uint32_t NTPsec,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000608 const uint32_t NTPfrac,
609 const RTCPReportBlock* received)
niklase@google.com470e71d2011-07-07 08:21:25 +0000610{
611 // sanity
612 if(pos + 52 >= IP_PACKET_SIZE)
613 {
614 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
615 return -2;
616 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000617 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000618
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000619 uint32_t posNumberOfReportBlocks = pos;
620 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000621
622 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000623 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000624
625 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
626 {
627 // shift old
628 _lastSendReport[i+1] = _lastSendReport[i];
629 _lastRTCPTime[i+1] =_lastRTCPTime[i];
630 }
631
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000632 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000633 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000634
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000635 uint32_t freqHz = 90000; // For video
636 if(_audio) {
637 freqHz = _rtpRtcp.CurrentSendFrequencyHz();
niklase@google.com470e71d2011-07-07 08:21:25 +0000638 }
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000639
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000640 // The timestamp of this RTCP packet should be estimated as the timestamp of
641 // the frame being captured at this moment. We are calculating that
642 // timestamp as the last frame's timestamp + the time since the last frame
643 // was captured.
644 {
645 // Needs protection since this method is called on the process thread.
646 CriticalSectionScoped lock(_criticalSectionRTCPSender);
647 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
648 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
649 (freqHz / 1000);
650 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000651
652 // Add sender data
653 // Save for our length field
654 pos++;
655 pos++;
656
657 // Add our own SSRC
658 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
659 pos += 4;
660 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000661 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000662 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000663 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000664 pos += 4;
665 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
666 pos += 4;
667
668 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000669 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000670 pos += 4;
671
672 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000673 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000674 pos += 4;
675
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000676 uint8_t numberOfReportBlocks = 0;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000677 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000678 if(retVal < 0)
679 {
680 //
681 return retVal ;
682 }
683 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
684
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000685 uint16_t len = uint16_t((pos/4) -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000686 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
687 return 0;
688}
689
690
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000691int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000692 uint32_t& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000693 size_t lengthCname = strlen(_CNAME);
694 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000695
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000696 // sanity
697 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
698 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
699 "%s invalid argument", __FUNCTION__);
700 return -2;
701 }
702 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000703
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000704 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000705 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
706 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000707
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000708 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000709 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000710 pos++;
711 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000712
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000713 // Add our own SSRC
714 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
715 pos += 4;
716
717 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000718 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000719
720 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000721 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000722
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000723 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000724
725 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
726 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000727 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000728
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000729 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000730 // We must have a zero field even if we have an even multiple of 4 bytes
731 if ((pos % 4) == 0) {
732 padding++;
733 rtcpbuffer[pos++]=0;
734 }
735 while ((pos % 4) != 0) {
736 padding++;
737 rtcpbuffer[pos++]=0;
738 }
739 SDESLength += padding;
740
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000741 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000742 _csrcCNAMEs.begin();
743
744 for(; it != _csrcCNAMEs.end(); it++) {
745 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000746 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000747
748 // Add SSRC
749 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000750 pos += 4;
751
752 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000753 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000754
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000755 size_t length = strlen(cname->name);
756 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000757
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000758 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000759 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000760
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000761 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000762
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000763 pos += length;
764 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000765 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000766
767 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000768 if((pos % 4) == 0){
769 padding++;
770 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000771 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000772 while((pos % 4) != 0){
773 padding++;
774 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000775 }
776 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000777 }
778 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000779 uint16_t buffer_length = (SDESLength / 4) - 1;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000780 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
781 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000782 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000783}
784
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000785int32_t
786RTCPSender::BuildRR(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000787 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000788 const uint32_t NTPsec,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000789 const uint32_t NTPfrac,
790 const RTCPReportBlock* received)
niklase@google.com470e71d2011-07-07 08:21:25 +0000791{
792 // sanity one block
793 if(pos + 32 >= IP_PACKET_SIZE)
794 {
795 return -2;
796 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000797 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000798
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000799 rtcpbuffer[pos++]=(uint8_t)0x80;
800 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000801
802 // Save for our length field
803 pos++;
804 pos++;
805
806 // Add our own SSRC
807 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
808 pos += 4;
809
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000810 uint8_t numberOfReportBlocks = 0;
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000811 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000812 if(retVal < 0)
813 {
814 return retVal;
815 }
816 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
817
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000818 uint16_t len = uint16_t((pos)/4 -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000819 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
820 return 0;
821}
822
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000823// From RFC 5450: Transmission Time Offsets in RTP Streams.
824// 0 1 2 3
825// 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
826// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
827// hdr |V=2|P| RC | PT=IJ=195 | length |
828// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
829// | inter-arrival jitter |
830// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
831// . .
832// . .
833// . .
834// | inter-arrival jitter |
835// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
836//
837// If present, this RTCP packet must be placed after a receiver report
838// (inside a compound RTCP packet), and MUST have the same value for RC
839// (reception report count) as the receiver report.
840
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000841int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000842RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000843 uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000844 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000845 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000846{
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000847 if (_reportBlocks.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000848 {
849 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
850 return 0;
851 }
852
853 // sanity
854 if(pos + 8 >= IP_PACKET_SIZE)
855 {
856 return -2;
857 }
858 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000859 uint8_t RC = 1;
860 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
861 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000862
863 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000864 rtcpbuffer[pos++]=(uint8_t)0;
865 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000866
867 // Add inter-arrival jitter
868 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
869 jitterTransmissionTimeOffset);
870 pos += 4;
871 return 0;
872}
873
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000874int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000875RTCPSender::BuildPLI(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000876{
877 // sanity
878 if(pos + 12 >= IP_PACKET_SIZE)
879 {
880 return -2;
881 }
882 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000883 uint8_t FMT = 1;
884 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
885 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000886
887 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000888 rtcpbuffer[pos++]=(uint8_t)0;
889 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000890
891 // Add our own SSRC
892 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
893 pos += 4;
894
895 // Add the remote SSRC
896 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
897 pos += 4;
898 return 0;
899}
900
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000901int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000902 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000903 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000904 // sanity
905 if(pos + 20 >= IP_PACKET_SIZE) {
906 return -2;
907 }
908 if (!repeat) {
909 _sequenceNumberFIR++; // do not increase if repetition
910 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000911
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000912 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000913 uint8_t FMT = 4;
914 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
915 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000916
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000917 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000918 rtcpbuffer[pos++] = (uint8_t)0;
919 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000920
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000921 // Add our own SSRC
922 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
923 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000924
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000925 // RFC 5104 4.3.1.2. Semantics
926 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000927 rtcpbuffer[pos++] = (uint8_t)0;
928 rtcpbuffer[pos++] = (uint8_t)0;
929 rtcpbuffer[pos++] = (uint8_t)0;
930 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000931
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000932 // Additional Feedback Control Information (FCI)
933 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
934 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000935
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000936 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
937 rtcpbuffer[pos++] = (uint8_t)0;
938 rtcpbuffer[pos++] = (uint8_t)0;
939 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000940 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000941}
942
943/*
944 0 1 2 3
945 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
946 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
947 | First | Number | PictureID |
948 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
949*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000950int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000951RTCPSender::BuildSLI(uint8_t* rtcpbuffer, uint32_t& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000952{
953 // sanity
954 if(pos + 16 >= IP_PACKET_SIZE)
955 {
956 return -2;
957 }
958 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000959 uint8_t FMT = 2;
960 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
961 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000962
963 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000964 rtcpbuffer[pos++]=(uint8_t)0;
965 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000966
967 // Add our own SSRC
968 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
969 pos += 4;
970
971 // Add the remote SSRC
972 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
973 pos += 4;
974
975 // Add first, number & picture ID 6 bits
976 // first = 0, 13 - bits
977 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000978 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000979 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
980 pos += 4;
981 return 0;
982}
983
984/*
985 0 1 2 3
986 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
987 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
988 | PB |0| Payload Type| Native RPSI bit string |
989 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
990 | defined per codec ... | Padding (0) |
991 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
992*/
993/*
994* Note: not generic made for VP8
995*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000996int32_t
997RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000998 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000999 const uint64_t pictureID,
1000 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +00001001{
1002 // sanity
1003 if(pos + 24 >= IP_PACKET_SIZE)
1004 {
1005 return -2;
1006 }
1007 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001008 uint8_t FMT = 3;
1009 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1010 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001011
1012 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001013 uint32_t bitsRequired = 7;
1014 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001015 while((pictureID>>bitsRequired) > 0)
1016 {
1017 bitsRequired += 7;
1018 bytesRequired++;
1019 }
1020
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001021 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001022 if(bytesRequired > 6)
1023 {
1024 size = 5;
1025 } else if(bytesRequired > 2)
1026 {
1027 size = 4;
1028 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001029 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001030 rtcpbuffer[pos++]=size;
1031
1032 // Add our own SSRC
1033 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1034 pos += 4;
1035
1036 // Add the remote SSRC
1037 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1038 pos += 4;
1039
1040 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001041 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001042 if(paddingBytes == 4)
1043 {
1044 paddingBytes = 0;
1045 }
1046 // add padding length in bits
1047 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1048 pos++;
1049
1050 // add payload type
1051 rtcpbuffer[pos] = payloadType;
1052 pos++;
1053
1054 // add picture ID
1055 for(int i = bytesRequired-1; i > 0; i--)
1056 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001057 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001058 pos++;
1059 }
1060 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001061 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001062 pos++;
1063
1064 // add padding
1065 for(int j = 0; j <paddingBytes; j++)
1066 {
1067 rtcpbuffer[pos] = 0;
1068 pos++;
1069 }
1070 return 0;
1071}
1072
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001073int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001074RTCPSender::BuildREMB(uint8_t* rtcpbuffer, uint32_t& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001075{
1076 // sanity
1077 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1078 {
1079 return -2;
1080 }
1081 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001082 uint8_t FMT = 15;
1083 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1084 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001085
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001086 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001087 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1088
1089 // Add our own SSRC
1090 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1091 pos += 4;
1092
1093 // Remote SSRC must be 0
1094 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1095 pos += 4;
1096
1097 rtcpbuffer[pos++]='R';
1098 rtcpbuffer[pos++]='E';
1099 rtcpbuffer[pos++]='M';
1100 rtcpbuffer[pos++]='B';
1101
1102 rtcpbuffer[pos++] = _lengthRembSSRC;
1103 // 6 bit Exp
1104 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001105 uint8_t brExp = 0;
1106 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001107 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001108 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001109 {
1110 brExp = i;
1111 break;
1112 }
1113 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001114 const uint32_t brMantissa = (_rembBitrate >> brExp);
1115 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1116 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1117 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001118
1119 for (int i = 0; i < _lengthRembSSRC; i++)
1120 {
1121 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1122 pos += 4;
1123 }
1124 return 0;
1125}
1126
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001127void
1128RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001129{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001130 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001131 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001132}
1133
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001134int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001135RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001136{
1137 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1138 // If the sender is an owner of the TMMBN -> send TMMBR
1139 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1140
niklase@google.com470e71d2011-07-07 08:21:25 +00001141 // get current bounding set from RTCP receiver
1142 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001143 // store in candidateSet, allocates one extra slot
1144 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001145
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001146 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1147 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1148 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001149 int32_t lengthOfBoundingSet
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001150 = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001151
1152 if(lengthOfBoundingSet > 0)
1153 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001154 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001155 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001156 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1157 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001158 {
1159 // do not send the same tuple
1160 return 0;
1161 }
1162 }
1163 if(!tmmbrOwner)
1164 {
1165 // use received bounding set as candidate set
1166 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001167 candidateSet->SetEntry(lengthOfBoundingSet,
1168 _tmmbr_Send,
1169 _packetOH_Send,
1170 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001171 int numCandidates = lengthOfBoundingSet+ 1;
1172
1173 // find bounding set
1174 TMMBRSet* boundingSet = NULL;
1175 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1176 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1177 {
1178 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1179 }
1180 if(!tmmbrOwner)
1181 {
1182 // did not enter bounding set, no meaning to send this request
1183 return 0;
1184 }
1185 }
1186 }
1187
1188 if(_tmmbr_Send)
1189 {
1190 // sanity
1191 if(pos + 20 >= IP_PACKET_SIZE)
1192 {
1193 return -2;
1194 }
1195 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001196 uint8_t FMT = 3;
1197 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1198 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001199
1200 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001201 rtcpbuffer[pos++]=(uint8_t)0;
1202 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001203
1204 // Add our own SSRC
1205 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1206 pos += 4;
1207
1208 // RFC 5104 4.2.1.2. Semantics
1209
1210 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001211 rtcpbuffer[pos++]=(uint8_t)0;
1212 rtcpbuffer[pos++]=(uint8_t)0;
1213 rtcpbuffer[pos++]=(uint8_t)0;
1214 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001215
1216 // Additional Feedback Control Information (FCI)
1217 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1218 pos += 4;
1219
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001220 uint32_t bitRate = _tmmbr_Send*1000;
1221 uint32_t mmbrExp = 0;
1222 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001223 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001224 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001225 {
1226 mmbrExp = i;
1227 break;
1228 }
1229 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001230 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001231
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001232 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1233 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1234 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1235 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001236 }
1237 return 0;
1238}
1239
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001240int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001241RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001242{
1243 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1244 if(boundingSet == NULL)
1245 {
1246 return -1;
1247 }
1248 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001249 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001250 {
1251 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1252 return -2;
1253 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001254 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001255 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001256 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1257 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001258
1259 //Add length later
1260 int posLength = pos;
1261 pos++;
1262 pos++;
1263
1264 // Add our own SSRC
1265 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1266 pos += 4;
1267
1268 // RFC 5104 4.2.2.2. Semantics
1269
1270 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001271 rtcpbuffer[pos++]=(uint8_t)0;
1272 rtcpbuffer[pos++]=(uint8_t)0;
1273 rtcpbuffer[pos++]=(uint8_t)0;
1274 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001275
1276 // Additional Feedback Control Information (FCI)
1277 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001278 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001279 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001280 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001281 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001282 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001283 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1284 pos += 4;
1285
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001286 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1287 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001288 for(int i=0; i<64; i++)
1289 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001290 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001291 {
1292 mmbrExp = i;
1293 break;
1294 }
1295 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001296 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1297 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001298
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001299 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1300 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1301 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1302 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001303 numBoundingSet++;
1304 }
1305 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001306 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1307 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1308 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001309 return 0;
1310}
1311
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001312int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001313RTCPSender::BuildAPP(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001314{
1315 // sanity
1316 if(_appData == NULL)
1317 {
1318 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1319 return -1;
1320 }
1321 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1322 {
1323 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1324 return -2;
1325 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001326 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001327
1328 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001329 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001330
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001331 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1332 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1333 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001334
1335 // Add our own SSRC
1336 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1337 pos += 4;
1338
1339 // Add our application name
1340 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1341 pos += 4;
1342
1343 // Add the data
1344 memcpy(rtcpbuffer +pos, _appData,_appLength);
1345 pos += _appLength;
1346 return 0;
1347}
1348
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001349int32_t
1350RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001351 uint32_t& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001352 const int32_t nackSize,
1353 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001354 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001355{
1356 // sanity
1357 if(pos + 16 >= IP_PACKET_SIZE)
1358 {
1359 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1360 return -2;
1361 }
1362
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001363 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001364 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001365 uint8_t FMT = 1;
1366 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1367 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001368
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001369 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001370 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001371 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001372
1373 // Add our own SSRC
1374 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1375 pos += 4;
1376
1377 // Add the remote SSRC
1378 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1379 pos += 4;
1380
edjee@google.com79b02892013-04-04 19:43:34 +00001381 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001382 // Build NACK bitmasks and write them to the RTCP message.
1383 // The nack list should be sorted and not contain duplicates if one
1384 // wants to build the smallest rtcp nack packet.
1385 int numOfNackFields = 0;
1386 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1387 (IP_PACKET_SIZE - pos) / 4);
1388 int i = 0;
1389 while (i < nackSize && numOfNackFields < maxNackFields) {
1390 stringBuilder.PushNACK(nackList[i]);
1391 uint16_t nack = nackList[i++];
1392 uint16_t bitmask = 0;
1393 while (i < nackSize) {
1394 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1395 if (shift >= 0 && shift <= 15) {
1396 stringBuilder.PushNACK(nackList[i]);
1397 bitmask |= (1 << shift);
1398 ++i;
1399 } else {
1400 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001401 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001402 }
1403 // Write the sequence number and the bitmask to the packet.
1404 assert(pos + 4 < IP_PACKET_SIZE);
1405 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
1406 pos += 2;
1407 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
1408 pos += 2;
1409 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001410 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001411 if (i != nackSize) {
1412 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1413 "Nack list to large for one packet.");
1414 }
1415 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001416 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001417 return 0;
1418}
1419
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001420int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001421RTCPSender::BuildBYE(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001422{
1423 // sanity
1424 if(pos + 8 >= IP_PACKET_SIZE)
1425 {
1426 return -2;
1427 }
1428 if(_includeCSRCs)
1429 {
1430 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001431 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1432 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001433
1434 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001435 rtcpbuffer[pos++]=(uint8_t)0;
1436 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001437
1438 // Add our own SSRC
1439 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1440 pos += 4;
1441
1442 // add CSRCs
1443 for(int i = 0; i < _CSRCs; i++)
1444 {
1445 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1446 pos += 4;
1447 }
1448 } else
1449 {
1450 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001451 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1452 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001453
1454 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001455 rtcpbuffer[pos++]=(uint8_t)0;
1456 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001457
1458 // Add our own SSRC
1459 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1460 pos += 4;
1461 }
1462 return 0;
1463}
1464
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001465int32_t
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001466RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001467{
1468 // sanity
1469 if(pos + 44 >= IP_PACKET_SIZE)
1470 {
1471 return -2;
1472 }
1473
1474 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001475 rtcpbuffer[pos++]=(uint8_t)0x80;
1476 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001477
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001478 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001479
1480 // handle length later on
1481 pos++;
1482 pos++;
1483
1484 // Add our own SSRC
1485 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1486 pos += 4;
1487
1488 // Add a VoIP metrics block
1489 rtcpbuffer[pos++]=7;
1490 rtcpbuffer[pos++]=0;
1491 rtcpbuffer[pos++]=0;
1492 rtcpbuffer[pos++]=8;
1493
1494 // Add the remote SSRC
1495 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1496 pos += 4;
1497
1498 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1499 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1500 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1501 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1502
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001503 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1504 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1505 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1506 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001507
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001508 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1509 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1510 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1511 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001512
1513 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1514 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1515 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1516 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1517
1518 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1519 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1520 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1521 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1522
1523 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1524 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001525 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1526 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001527
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001528 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1529 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1530 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1531 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001532
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001533 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1534 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001535 return 0;
1536}
1537
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001538int32_t
tnakamura@webrtc.orgaa4d96a2013-07-16 19:25:04 +00001539RTCPSender::SendRTCP(const uint32_t packetTypeFlags,
1540 const int32_t nackSize, // NACK
1541 const uint16_t* nackList, // NACK
1542 const bool repeat, // FIR
1543 const uint64_t pictureID) // SLI & RPSI
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 {
tnakamura@webrtc.orgaa4d96a2013-07-16 19:25:04 +00001575 // get statistics from our RTPreceiver outside critsect
1576 if(_rtpRtcp.ReportBlockStatistics(&received.fractionLost,
1577 &received.cumulativeLost,
1578 &received.extendedHighSeqNum,
1579 &received.jitter,
1580 &jitterTransmissionOffset) == 0)
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001581 {
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001582 hasReceived = true;
1583
1584 uint32_t lastReceivedRRNTPsecs = 0;
1585 uint32_t lastReceivedRRNTPfrac = 0;
1586 uint32_t remoteSR = 0;
1587
1588 // ok even if we have not received a SR, we will send 0 in that case
1589 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1590 lastReceivedRRNTPfrac,
1591 remoteSR);
1592
1593 // get our NTP as late as possible to avoid a race
1594 _clock->CurrentNtp(NTPsec, NTPfrac);
1595
1596 // Delay since last received report
1597 uint32_t delaySinceLastReceivedSR = 0;
1598 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
1599 {
1600 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1601 uint32_t now=NTPsec&0x0000FFFF;
1602 now <<=16;
1603 now += (NTPfrac&0xffff0000)>>16;
1604
1605 uint32_t receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
1606 receiveTime <<=16;
1607 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1608
1609 delaySinceLastReceivedSR = now-receiveTime;
1610 }
1611 received.delaySinceLastSR = delaySinceLastReceivedSR;
1612 received.lastSR = remoteSR;
1613 } else
1614 {
1615 // we need to send our NTP even if we dont have received any reports
1616 _clock->CurrentNtp(NTPsec, NTPfrac);
1617 }
1618 }
1619
1620 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1621
1622 if(_TMMBR ) // attach TMMBR to send and receive reports
1623 {
1624 rtcpPacketTypeFlags |= kRtcpTmmbr;
1625 }
1626 if(_appSend)
1627 {
1628 rtcpPacketTypeFlags |= kRtcpApp;
1629 _appSend = false;
1630 }
1631 if(_REMB && _sendREMB)
1632 {
1633 // Always attach REMB to SR if that is configured. Note that REMB is
1634 // only sent on one of the RTP modules in the REMB group.
1635 rtcpPacketTypeFlags |= kRtcpRemb;
1636 }
1637 if(_xrSendVoIPMetric)
1638 {
1639 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1640 _xrSendVoIPMetric = false;
1641 }
1642 if(_sendTMMBN) // set when having received a TMMBR
1643 {
1644 rtcpPacketTypeFlags |= kRtcpTmmbn;
1645 _sendTMMBN = false;
1646 }
1647
1648 if(_method == kRtcpCompound)
1649 {
1650 if(_sending)
1651 {
1652 rtcpPacketTypeFlags |= kRtcpSr;
1653 } else
1654 {
1655 rtcpPacketTypeFlags |= kRtcpRr;
1656 }
1657 if (_IJ && hasReceived)
1658 {
1659 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1660 }
1661 } else if(_method == kRtcpNonCompound)
1662 {
1663 if(rtcpPacketTypeFlags & kRtcpReport)
1664 {
1665 if(_sending)
1666 {
1667 rtcpPacketTypeFlags |= kRtcpSr;
1668 } else
1669 {
1670 rtcpPacketTypeFlags |= kRtcpRr;
1671 }
1672 }
1673 }
1674 if( rtcpPacketTypeFlags & kRtcpRr ||
1675 rtcpPacketTypeFlags & kRtcpSr)
1676 {
1677 // generate next time to send a RTCP report
1678 // seeded from RTP constructor
1679 int32_t random = rand() % 1000;
1680 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1681
1682 if(_audio)
1683 {
1684 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
1685 }else
1686 {
1687 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1688 if(_sending)
1689 {
1690 // calc bw for video 360/sendBW in kbit/s
1691 uint32_t sendBitrateKbit = 0;
1692 uint32_t videoRate = 0;
1693 uint32_t fecRate = 0;
1694 uint32_t nackRate = 0;
1695 _rtpRtcp.BitrateSent(&sendBitrateKbit,
1696 &videoRate,
1697 &fecRate,
1698 &nackRate);
1699 sendBitrateKbit /= 1000;
1700 if(sendBitrateKbit != 0)
1701 {
1702 minIntervalMs = 360000/sendBitrateKbit;
1703 }
1704 }
1705 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1706 {
1707 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1708 }
1709 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1710 }
1711 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1712 }
1713
1714 // if the data does not fitt in the packet we fill it as much as possible
1715 int32_t buildVal = 0;
1716
1717 if(rtcpPacketTypeFlags & kRtcpSr)
1718 {
1719 if(hasReceived)
1720 {
1721 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
1722 } else
1723 {
1724 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac);
1725 }
1726 if(buildVal == -1)
1727 {
1728 return -1; // error
1729
1730 }else if(buildVal == -2)
1731 {
1732 break; // out of buffer
1733 }
1734 buildVal = BuildSDEC(rtcpbuffer, pos);
1735 if(buildVal == -1)
1736 {
1737 return -1; // error
1738
1739 }else if(buildVal == -2)
1740 {
1741 break; // out of buffer
1742 }
1743
1744 }else if(rtcpPacketTypeFlags & kRtcpRr)
1745 {
1746 if(hasReceived)
1747 {
1748 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
1749 }else
1750 {
1751 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
1752 }
1753 if(buildVal == -1)
1754 {
1755 return -1; // error
1756
1757 }else if(buildVal == -2)
1758 {
1759 break; // out of buffer
1760 }
1761 // only of set
1762 if(_CNAME[0] != 0)
1763 {
1764 buildVal = BuildSDEC(rtcpbuffer, pos);
1765 if(buildVal == -1)
1766 {
1767 return -1; // error
1768 }
1769 }
1770 }
1771 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1772 {
1773 // If present, this RTCP packet must be placed after a
1774 // receiver report.
1775 buildVal = BuildExtendedJitterReport(rtcpbuffer,
1776 pos,
1777 jitterTransmissionOffset);
1778 if(buildVal == -1)
1779 {
1780 return -1; // error
1781 }
1782 else if(buildVal == -2)
1783 {
1784 break; // out of buffer
1785 }
1786 }
1787 if(rtcpPacketTypeFlags & kRtcpPli)
1788 {
1789 buildVal = BuildPLI(rtcpbuffer, pos);
1790 if(buildVal == -1)
1791 {
1792 return -1; // error
1793
1794 }else if(buildVal == -2)
1795 {
1796 break; // out of buffer
1797 }
1798 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
1799 _pliCount++;
1800 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC, _pliCount);
1801 }
1802 if(rtcpPacketTypeFlags & kRtcpFir)
1803 {
1804 buildVal = BuildFIR(rtcpbuffer, pos, repeat);
1805 if(buildVal == -1)
1806 {
1807 return -1; // error
1808
1809 }else if(buildVal == -2)
1810 {
1811 break; // out of buffer
1812 }
1813 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
1814 _fullIntraRequestCount++;
1815 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
1816 _fullIntraRequestCount);
1817 }
1818 if(rtcpPacketTypeFlags & kRtcpSli)
1819 {
1820 buildVal = BuildSLI(rtcpbuffer, pos, (uint8_t)pictureID);
1821 if(buildVal == -1)
1822 {
1823 return -1; // error
1824
1825 }else if(buildVal == -2)
1826 {
1827 break; // out of buffer
1828 }
1829 }
1830 if(rtcpPacketTypeFlags & kRtcpRpsi)
1831 {
1832 const int8_t payloadType = _rtpRtcp.SendPayloadType();
1833 if(payloadType == -1)
1834 {
1835 return -1;
1836 }
1837 buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (uint8_t)payloadType);
1838 if(buildVal == -1)
1839 {
1840 return -1; // error
1841
1842 }else if(buildVal == -2)
1843 {
1844 break; // out of buffer
1845 }
1846 }
1847 if(rtcpPacketTypeFlags & kRtcpRemb)
1848 {
1849 buildVal = BuildREMB(rtcpbuffer, pos);
1850 if(buildVal == -1)
1851 {
1852 return -1; // error
1853
1854 }else if(buildVal == -2)
1855 {
1856 break; // out of buffer
1857 }
1858 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1859 }
1860 if(rtcpPacketTypeFlags & kRtcpBye)
1861 {
1862 buildVal = BuildBYE(rtcpbuffer, pos);
1863 if(buildVal == -1)
1864 {
1865 return -1; // error
1866
1867 }else if(buildVal == -2)
1868 {
1869 break; // out of buffer
1870 }
1871 }
1872 if(rtcpPacketTypeFlags & kRtcpApp)
1873 {
1874 buildVal = BuildAPP(rtcpbuffer, pos);
1875 if(buildVal == -1)
1876 {
1877 return -1; // error
1878
1879 }else if(buildVal == -2)
1880 {
1881 break; // out of buffer
1882 }
1883 }
1884 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1885 {
1886 buildVal = BuildTMMBR(rtcpbuffer, pos);
1887 if(buildVal == -1)
1888 {
1889 return -1; // error
1890
1891 }else if(buildVal == -2)
1892 {
1893 break; // out of buffer
1894 }
1895 }
1896 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1897 {
1898 buildVal = BuildTMMBN(rtcpbuffer, pos);
1899 if(buildVal == -1)
1900 {
1901 return -1; // error
1902
1903 }else if(buildVal == -2)
1904 {
1905 break; // out of buffer
1906 }
1907 }
1908 if(rtcpPacketTypeFlags & kRtcpNack)
1909 {
1910 std::string nackString;
1911 buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList,
1912 &nackString);
1913 if(buildVal == -1)
1914 {
1915 return -1; // error
1916
1917 }else if(buildVal == -2)
1918 {
1919 break; // out of buffer
1920 }
1921 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
1922 "nacks", TRACE_STR_COPY(nackString.c_str()));
1923 _nackCount++;
1924 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC, _nackCount);
1925 }
1926 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1927 {
1928 buildVal = BuildVoIPMetric(rtcpbuffer, pos);
1929 if(buildVal == -1)
1930 {
1931 return -1; // error
1932
1933 }else if(buildVal == -2)
1934 {
1935 break; // out of buffer
1936 }
1937 }
1938 }while (false);
1939 // Sanity don't send empty packets.
1940 if (pos == 0)
1941 {
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001942 return -1;
1943 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00001944 return SendToNetwork(rtcpbuffer, (uint16_t)pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001945}
1946
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001947int32_t
1948RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
1949 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001950{
1951 CriticalSectionScoped lock(_criticalSectionTransport);
1952 if(_cbTransport)
1953 {
1954 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1955 {
1956 return 0;
1957 }
1958 }
1959 return -1;
1960}
1961
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001962int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00001963RTCPSender::SetCSRCStatus(const bool include)
1964{
1965 _includeCSRCs = include;
1966 return 0;
1967}
1968
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001969int32_t
1970RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
1971 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00001972{
1973 if(arrLength > kRtpCsrcSize)
1974 {
1975 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1976 assert(false);
1977 return -1;
1978 }
1979
1980 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1981
1982 for(int i = 0; i < arrLength;i++)
1983 {
1984 _CSRC[i] = arrOfCSRC[i];
1985 }
1986 _CSRCs = arrLength;
1987 return 0;
1988}
1989
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001990int32_t
1991RTCPSender::SetApplicationSpecificData(const uint8_t subType,
1992 const uint32_t name,
1993 const uint8_t* data,
1994 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001995{
1996 if(length %4 != 0)
1997 {
1998 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1999 return -1;
2000 }
2001 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2002
2003 if(_appData)
2004 {
2005 delete [] _appData;
2006 }
2007
2008 _appSend = true;
2009 _appSubType = subType;
2010 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002011 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002012 _appLength = length;
2013 memcpy(_appData, data, length);
2014 return 0;
2015}
2016
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002017int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002018RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2019{
2020 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2021 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2022
2023 _xrSendVoIPMetric = true;
2024 return 0;
2025}
2026
2027// called under critsect _criticalSectionRTCPSender
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002028int32_t RTCPSender::AddReportBlocks(uint8_t* rtcpbuffer,
2029 uint32_t& pos,
2030 uint8_t& numberOfReportBlocks,
2031 const RTCPReportBlock* received,
2032 const uint32_t NTPsec,
2033 const uint32_t NTPfrac) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002034 // sanity one block
2035 if(pos + 24 >= IP_PACKET_SIZE) {
2036 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2037 "%s invalid argument", __FUNCTION__);
2038 return -1;
2039 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002040 numberOfReportBlocks = _reportBlocks.size();
2041 if (received) {
2042 // add our multiple RR to numberOfReportBlocks
2043 numberOfReportBlocks++;
2044 }
2045 if (received) {
2046 // answer to the one that sends to me
2047 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
2048
2049 // Remote SSRC
2050 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
2051 pos += 4;
2052
2053 // fraction lost
2054 rtcpbuffer[pos++]=received->fractionLost;
2055
2056 // cumulative loss
2057 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2058 received->cumulativeLost);
2059 pos += 3;
2060 // extended highest seq_no, contain the highest sequence number received
2061 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2062 received->extendedHighSeqNum);
2063 pos += 4;
2064
2065 //Jitter
2066 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
2067 pos += 4;
2068
2069 // Last SR timestamp, our NTP time when we received the last report
2070 // This is the value that we read from the send report packet not when we
2071 // received it...
2072 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
2073 pos += 4;
2074
2075 // Delay since last received report,time since we received the report
2076 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2077 received->delaySinceLastSR);
2078 pos += 4;
2079 }
2080 if ((pos + _reportBlocks.size() * 24) >= IP_PACKET_SIZE) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002081 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2082 "%s invalid argument", __FUNCTION__);
2083 return -1;
2084 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002085 std::map<uint32_t, RTCPReportBlock*>::iterator it =
2086 _reportBlocks.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002087
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002088 for (; it != _reportBlocks.end(); it++) {
2089 // we can have multiple report block in a conference
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002090 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002091 RTCPReportBlock* reportBlock = it->second;
2092 if (reportBlock) {
2093 // Remote SSRC
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002094 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
2095 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002096
2097 // fraction lost
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002098 rtcpbuffer[pos++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002099
2100 // cumulative loss
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002101 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002102 reportBlock->cumulativeLost);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002103 pos += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002104
2105 // extended highest seq_no, contain the highest sequence number received
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002106 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002107 reportBlock->extendedHighSeqNum);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002108 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002109
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002110 //Jitter
2111 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002112 reportBlock->jitter);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002113 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002114
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002115 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002116 reportBlock->lastSR);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002117 pos += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002118
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002119 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002120 reportBlock->delaySinceLastSR);
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002121 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002122 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002123 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +00002124 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00002125}
2126
2127// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002128int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002129RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002130 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002131{
2132 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2133
2134 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2135 {
2136 _sendTMMBN = true;
2137 return 0;
2138 }
2139 return -1;
2140}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002141} // namespace webrtc