blob: ef97f85ac4e959712b44069181a2f1c6cf65794d [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
11#include "rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000013#include <cassert> // assert
14#include <cstdlib> // rand
15#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
niklase@google.com470e71d2011-07-07 08:21:25 +000017#include "common_types.h"
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000018#include "modules/rtp_rtcp/source/rtp_rtcp_impl.h"
19#include "system_wrappers/interface/critical_section_wrapper.h"
20#include "system_wrappers/interface/trace.h"
edjee@google.com79b02892013-04-04 19:43:34 +000021#include "system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000022
niklase@google.com470e71d2011-07-07 08:21:25 +000023namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000024
25using RTCPUtility::RTCPCnameInformation;
26
edjee@google.com79b02892013-04-04 19:43:34 +000027NACKStringBuilder::NACKStringBuilder() :
28 _stream(""), _count(0), _consecutive(false)
29{
30 // Empty.
31}
32
pbos@webrtc.org2f446732013-04-08 11:08:41 +000033void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000034{
35 if (_count == 0)
36 {
37 _stream << nack;
38 } else if (nack == _prevNack + 1)
39 {
40 _consecutive = true;
41 } else
42 {
43 if (_consecutive)
44 {
45 _stream << "-" << _prevNack;
46 _consecutive = false;
47 }
48 _stream << "," << nack;
49 }
50 _count++;
51 _prevNack = nack;
52}
53
54std::string NACKStringBuilder::GetResult()
55{
56 if (_consecutive)
57 {
58 _stream << "-" << _prevNack;
59 _consecutive = false;
60 }
61 return _stream.str();
62}
63
pbos@webrtc.org2f446732013-04-08 11:08:41 +000064RTCPSender::RTCPSender(const int32_t id,
niklase@google.com470e71d2011-07-07 08:21:25 +000065 const bool audio,
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000066 Clock* clock,
pwestin@webrtc.org741da942011-09-20 13:52:04 +000067 ModuleRtpRtcpImpl* owner) :
niklase@google.com470e71d2011-07-07 08:21:25 +000068 _id(id),
69 _audio(audio),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000070 _clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000071 _method(kRtcpOff),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000072 _rtpRtcp(*owner),
henrike@webrtc.org65573f22011-12-13 19:17:27 +000073 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000074 _cbTransport(NULL),
75
henrike@webrtc.org65573f22011-12-13 19:17:27 +000076 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000077 _usingNack(false),
78 _sending(false),
79 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000080 _REMB(false),
81 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000082 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +000083 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000084 _nextTimeToSendRTCP(0),
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000085 start_timestamp_(0),
86 last_rtp_timestamp_(0),
87 last_frame_capture_time_ms_(-1),
niklase@google.com470e71d2011-07-07 08:21:25 +000088 _SSRC(0),
89 _remoteSSRC(0),
90 _CNAME(),
91 _reportBlocks(),
92 _csrcCNAMEs(),
93
94 _cameraDelayMS(0),
95
96 _lastSendReport(),
97 _lastRTCPTime(),
98
99 _CSRCs(0),
100 _CSRC(),
101 _includeCSRCs(true),
102
103 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000104
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000105 _lengthRembSSRC(0),
106 _sizeRembSSRC(0),
107 _rembSSRC(NULL),
108 _rembBitrate(0),
109
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000110 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000111 _tmmbr_Send(0),
112 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000113
114 _appSend(false),
115 _appSubType(0),
116 _appName(),
117 _appData(NULL),
118 _appLength(0),
119 _xrSendVoIPMetric(false),
edjee@google.com79b02892013-04-04 19:43:34 +0000120 _xrVoIPMetric(),
121 _nackCount(0),
122 _pliCount(0),
123 _fullIntraRequestCount(0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000124{
125 memset(_CNAME, 0, sizeof(_CNAME));
126 memset(_lastSendReport, 0, sizeof(_lastSendReport));
127 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
128
129 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
130}
131
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000132RTCPSender::~RTCPSender() {
133 delete [] _rembSSRC;
134 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000135
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000136 while (!_reportBlocks.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000137 std::map<uint32_t, RTCPReportBlock*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000138 _reportBlocks.begin();
139 delete it->second;
140 _reportBlocks.erase(it);
141 }
142 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000143 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000144 _csrcCNAMEs.begin();
145 delete it->second;
146 _csrcCNAMEs.erase(it);
147 }
148 delete _criticalSectionTransport;
149 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000150
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000151 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000152}
153
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000154int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000155RTCPSender::Init()
156{
157 CriticalSectionScoped lock(_criticalSectionRTCPSender);
158
159 _method = kRtcpOff;
160 _cbTransport = NULL;
161 _usingNack = false;
162 _sending = false;
163 _sendTMMBN = false;
164 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000165 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000166 _REMB = false;
167 _sendREMB = false;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000168 last_rtp_timestamp_ = 0;
169 last_frame_capture_time_ms_ = -1;
170 start_timestamp_ = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000171 _SSRC = 0;
172 _remoteSSRC = 0;
173 _cameraDelayMS = 0;
174 _sequenceNumberFIR = 0;
175 _tmmbr_Send = 0;
176 _packetOH_Send = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000177 _nextTimeToSendRTCP = 0;
178 _CSRCs = 0;
179 _appSend = false;
180 _appSubType = 0;
181
182 if(_appData)
183 {
184 delete [] _appData;
185 _appData = NULL;
186 }
187 _appLength = 0;
188
189 _xrSendVoIPMetric = false;
190
191 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
192 memset(_CNAME, 0, sizeof(_CNAME));
193 memset(_lastSendReport, 0, sizeof(_lastSendReport));
194 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
edjee@google.com79b02892013-04-04 19:43:34 +0000195
196 _nackCount = 0;
197 _pliCount = 0;
198 _fullIntraRequestCount = 0;
199
niklase@google.com470e71d2011-07-07 08:21:25 +0000200 return 0;
201}
202
203void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000204RTCPSender::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +0000205{
206 _id = id;
207}
208
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000209int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000210RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
211{
212 CriticalSectionScoped lock(_criticalSectionTransport);
213 _cbTransport = outgoingTransport;
214 return 0;
215}
216
217RTCPMethod
218RTCPSender::Status() const
219{
220 CriticalSectionScoped lock(_criticalSectionRTCPSender);
221 return _method;
222}
223
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000224int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000225RTCPSender::SetRTCPStatus(const RTCPMethod method)
226{
227 CriticalSectionScoped lock(_criticalSectionRTCPSender);
228 if(method != kRtcpOff)
229 {
230 if(_audio)
231 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000232 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000233 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000234 } else
235 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000236 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000237 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000238 }
239 }
240 _method = method;
241 return 0;
242}
243
244bool
245RTCPSender::Sending() const
246{
247 CriticalSectionScoped lock(_criticalSectionRTCPSender);
248 return _sending;
249}
250
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000251int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000252RTCPSender::SetSendingStatus(const bool sending)
253{
254 bool sendRTCPBye = false;
255 {
256 CriticalSectionScoped lock(_criticalSectionRTCPSender);
257
258 if(_method != kRtcpOff)
259 {
260 if(sending == false && _sending == true)
261 {
262 // Trigger RTCP bye
263 sendRTCPBye = true;
264 }
265 }
266 _sending = sending;
267 }
268 if(sendRTCPBye)
269 {
270 return SendRTCP(kRtcpBye);
271 }
272 return 0;
273}
274
275bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000276RTCPSender::REMB() const
277{
278 CriticalSectionScoped lock(_criticalSectionRTCPSender);
279 return _REMB;
280}
281
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000282int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000283RTCPSender::SetREMBStatus(const bool enable)
284{
285 CriticalSectionScoped lock(_criticalSectionRTCPSender);
286 _REMB = enable;
287 return 0;
288}
289
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000290int32_t
291RTCPSender::SetREMBData(const uint32_t bitrate,
292 const uint8_t numberOfSSRC,
293 const uint32_t* SSRC)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000294{
295 CriticalSectionScoped lock(_criticalSectionRTCPSender);
296 _rembBitrate = bitrate;
297
298 if(_sizeRembSSRC < numberOfSSRC)
299 {
300 delete [] _rembSSRC;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000301 _rembSSRC = new uint32_t[numberOfSSRC];
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000302 _sizeRembSSRC = numberOfSSRC;
303 }
304
305 _lengthRembSSRC = numberOfSSRC;
306 for (int i = 0; i < numberOfSSRC; i++)
307 {
308 _rembSSRC[i] = SSRC[i];
309 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000310 _sendREMB = true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000311 return 0;
312}
313
314bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000315RTCPSender::TMMBR() const
316{
317 CriticalSectionScoped lock(_criticalSectionRTCPSender);
318 return _TMMBR;
319}
320
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000321int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000322RTCPSender::SetTMMBRStatus(const bool enable)
323{
324 CriticalSectionScoped lock(_criticalSectionRTCPSender);
325 _TMMBR = enable;
326 return 0;
327}
328
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000329bool
330RTCPSender::IJ() const
331{
332 CriticalSectionScoped lock(_criticalSectionRTCPSender);
333 return _IJ;
334}
335
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000336int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000337RTCPSender::SetIJStatus(const bool enable)
338{
339 CriticalSectionScoped lock(_criticalSectionRTCPSender);
340 _IJ = enable;
341 return 0;
342}
343
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000344void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
345 start_timestamp_ = start_timestamp;
346}
347
348void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
349 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000350 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000351 last_rtp_timestamp_ = rtp_timestamp;
352 if (capture_time_ms < 0) {
353 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000354 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000355 } else {
356 last_frame_capture_time_ms_ = capture_time_ms;
357 }
358}
359
niklase@google.com470e71d2011-07-07 08:21:25 +0000360void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000361RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000362{
363 CriticalSectionScoped lock(_criticalSectionRTCPSender);
364
365 if(_SSRC != 0)
366 {
367 // not first SetSSRC, probably due to a collision
368 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000369 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000370 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000371 }
372 _SSRC = ssrc;
373}
374
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000375int32_t
376RTCPSender::SetRemoteSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000377{
378 CriticalSectionScoped lock(_criticalSectionRTCPSender);
379 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000380 return 0;
381}
382
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000383int32_t
384RTCPSender::SetCameraDelay(const int32_t delayMS)
niklase@google.com470e71d2011-07-07 08:21:25 +0000385{
386 CriticalSectionScoped lock(_criticalSectionRTCPSender);
387 if(delayMS > 1000 || delayMS < -1000)
388 {
389 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
390 return -1;
391 }
392 _cameraDelayMS = delayMS;
393 return 0;
394}
395
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000396int32_t RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000397 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000398 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000399 cName[RTCP_CNAME_SIZE - 1] = 0;
400 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000401 return 0;
402}
403
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000404int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000405 if (!cName)
406 return -1;
407
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000408 CriticalSectionScoped lock(_criticalSectionRTCPSender);
409 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
410 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
411 return 0;
412}
413
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000414int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
415 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000416 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000417 CriticalSectionScoped lock(_criticalSectionRTCPSender);
418 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
419 return -1;
420 }
421 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000422 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
423 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000424 _csrcCNAMEs[SSRC] = ptr;
425 return 0;
426}
427
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000428int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000429 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000430 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000431 _csrcCNAMEs.find(SSRC);
432
433 if (it == _csrcCNAMEs.end()) {
434 return -1;
435 }
436 delete it->second;
437 _csrcCNAMEs.erase(it);
438 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000439}
440
441bool
442RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
443{
444/*
445 For audio we use a fix 5 sec interval
446
447 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
448 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
449
450
451From RFC 3550
452
453 MAX RTCP BW is 5% if the session BW
454 A send report is approximately 65 bytes inc CNAME
455 A report report is approximately 28 bytes
456
457 The RECOMMENDED value for the reduced minimum in seconds is 360
458 divided by the session bandwidth in kilobits/second. This minimum
459 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
460
461 If the participant has not yet sent an RTCP packet (the variable
462 initial is true), the constant Tmin is set to 2.5 seconds, else it
463 is set to 5 seconds.
464
465 The interval between RTCP packets is varied randomly over the
466 range [0.5,1.5] times the calculated interval to avoid unintended
467 synchronization of all participants
468
469 if we send
470 If the participant is a sender (we_sent true), the constant C is
471 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
472 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
473 number of senders.
474
475 if we receive only
476 If we_sent is not true, the constant C is set
477 to the average RTCP packet size divided by 75% of the RTCP
478 bandwidth. The constant n is set to the number of receivers
479 (members - senders). If the number of senders is greater than
480 25%, senders and receivers are treated together.
481
482 reconsideration NOT required for peer-to-peer
483 "timer reconsideration" is
484 employed. This algorithm implements a simple back-off mechanism
485 which causes users to hold back RTCP packet transmission if the
486 group sizes are increasing.
487
488 n = number of members
489 C = avg_size/(rtcpBW/4)
490
491 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
492
493 4. The calculated interval T is set to a number uniformly distributed
494 between 0.5 and 1.5 times the deterministic calculated interval.
495
496 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
497 for the fact that the timer reconsideration algorithm converges to
498 a value of the RTCP bandwidth below the intended average
499*/
500
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000501 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000502
503 CriticalSectionScoped lock(_criticalSectionRTCPSender);
504
niklase@google.com470e71d2011-07-07 08:21:25 +0000505 if(_method == kRtcpOff)
506 {
507 return false;
508 }
509
niklase@google.com470e71d2011-07-07 08:21:25 +0000510 if(!_audio && sendKeyframeBeforeRTP)
511 {
512 // for video key-frames we want to send the RTCP before the large key-frame
513 // if we have a 100 ms margin
514 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
515 }
516
517 if(now > _nextTimeToSendRTCP)
518 {
519 return true;
520
521 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
522 {
523 // wrap
524 return true;
525 }
526 return false;
527}
528
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000529uint32_t
530RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000531{
532 CriticalSectionScoped lock(_criticalSectionRTCPSender);
533
534 lastRTCPTime = _lastRTCPTime[0];
535 return _lastSendReport[0];
536}
537
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000538uint32_t
539RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000540{
541 CriticalSectionScoped lock(_criticalSectionRTCPSender);
542
543 // This is only saved when we are the sender
544 if((_lastSendReport[0] == 0) || (sendReport == 0))
545 {
546 return 0; // will be ignored
547 } else
548 {
549 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
550 {
551 if( _lastSendReport[i] == sendReport)
552 {
553 return _lastRTCPTime[i];
554 }
555 }
556 }
557 return 0;
558}
559
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000560int32_t RTCPSender::AddReportBlock(const uint32_t SSRC,
561 const RTCPReportBlock* reportBlock) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000562 if (reportBlock == NULL) {
563 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
564 "%s invalid argument", __FUNCTION__);
565 return -1;
566 }
567 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000568
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000569 if (_reportBlocks.size() >= RTCP_MAX_REPORT_BLOCKS) {
570 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
571 "%s invalid argument", __FUNCTION__);
572 return -1;
573 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000574 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000575 _reportBlocks.find(SSRC);
576 if (it != _reportBlocks.end()) {
577 delete it->second;
578 _reportBlocks.erase(it);
579 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000580 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
581 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
582 _reportBlocks[SSRC] = copyReportBlock;
583 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000584}
585
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000586int32_t RTCPSender::RemoveReportBlock(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000587 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000588
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000589 std::map<uint32_t, RTCPReportBlock*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000590 _reportBlocks.find(SSRC);
591
592 if (it == _reportBlocks.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000593 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000594 }
595 delete it->second;
596 _reportBlocks.erase(it);
597 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000598}
599
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000600int32_t
601RTCPSender::BuildSR(uint8_t* rtcpbuffer,
602 uint32_t& pos,
603 const uint32_t NTPsec,
604 const uint32_t NTPfrac,
niklase@google.com470e71d2011-07-07 08:21:25 +0000605 const RTCPReportBlock* received)
606{
607 // sanity
608 if(pos + 52 >= IP_PACKET_SIZE)
609 {
610 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
611 return -2;
612 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000613 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000614
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000615 uint32_t posNumberOfReportBlocks = pos;
616 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000617
618 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000619 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000620
621 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
622 {
623 // shift old
624 _lastSendReport[i+1] = _lastSendReport[i];
625 _lastRTCPTime[i+1] =_lastRTCPTime[i];
626 }
627
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000628 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac);
629 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000630
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000631 uint32_t freqHz = 90000; // For video
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000632 if(_audio) {
633 freqHz = _rtpRtcp.CurrentSendFrequencyHz();
niklase@google.com470e71d2011-07-07 08:21:25 +0000634 }
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000635
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000636 // The timestamp of this RTCP packet should be estimated as the timestamp of
637 // the frame being captured at this moment. We are calculating that
638 // timestamp as the last frame's timestamp + the time since the last frame
639 // was captured.
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000640 {
641 // Needs protection since this method is called on the process thread.
642 CriticalSectionScoped lock(_criticalSectionRTCPSender);
643 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
644 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
645 (freqHz / 1000);
646 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000647
648 // Add sender data
649 // Save for our length field
650 pos++;
651 pos++;
652
653 // Add our own SSRC
654 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
655 pos += 4;
656 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000657 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000658 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000659 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000660 pos += 4;
661 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
662 pos += 4;
663
664 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000665 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000666 pos += 4;
667
668 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000669 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000670 pos += 4;
671
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000672 uint8_t numberOfReportBlocks = 0;
673 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000674 if(retVal < 0)
675 {
676 //
677 return retVal ;
678 }
679 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
680
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000681 uint16_t len = uint16_t((pos/4) -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000682 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
683 return 0;
684}
685
686
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000687int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer,
688 uint32_t& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000689 size_t lengthCname = strlen(_CNAME);
690 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000691
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000692 // sanity
693 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
694 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
695 "%s invalid argument", __FUNCTION__);
696 return -2;
697 }
698 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000699
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000700 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000701 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
702 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000703
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000704 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000705 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000706 pos++;
707 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000708
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000709 // Add our own SSRC
710 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
711 pos += 4;
712
713 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000714 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000715
716 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000717 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000718
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000719 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000720
721 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
722 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000723 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000724
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000725 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000726 // We must have a zero field even if we have an even multiple of 4 bytes
727 if ((pos % 4) == 0) {
728 padding++;
729 rtcpbuffer[pos++]=0;
730 }
731 while ((pos % 4) != 0) {
732 padding++;
733 rtcpbuffer[pos++]=0;
734 }
735 SDESLength += padding;
736
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000737 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000738 _csrcCNAMEs.begin();
739
740 for(; it != _csrcCNAMEs.end(); it++) {
741 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000742 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000743
744 // Add SSRC
745 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000746 pos += 4;
747
748 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000749 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000750
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000751 size_t length = strlen(cname->name);
752 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000753
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000754 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000755 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000756
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000757 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000758
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000759 pos += length;
760 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000761 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000762
763 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000764 if((pos % 4) == 0){
765 padding++;
766 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000767 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000768 while((pos % 4) != 0){
769 padding++;
770 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000771 }
772 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000773 }
774 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000775 uint16_t buffer_length = (SDESLength / 4) - 1;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000776 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
777 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000778 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000779}
780
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000781int32_t
782RTCPSender::BuildRR(uint8_t* rtcpbuffer,
783 uint32_t& pos,
784 const uint32_t NTPsec,
785 const uint32_t NTPfrac,
niklase@google.com470e71d2011-07-07 08:21:25 +0000786 const RTCPReportBlock* received)
787{
788 // sanity one block
789 if(pos + 32 >= IP_PACKET_SIZE)
790 {
791 return -2;
792 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000793 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000794
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000795 rtcpbuffer[pos++]=(uint8_t)0x80;
796 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000797
798 // Save for our length field
799 pos++;
800 pos++;
801
802 // Add our own SSRC
803 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
804 pos += 4;
805
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000806 uint8_t numberOfReportBlocks = 0;
807 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000808 if(retVal < 0)
809 {
810 return retVal;
811 }
812 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
813
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000814 uint16_t len = uint16_t((pos)/4 -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000815 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
816 return 0;
817}
818
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000819// From RFC 5450: Transmission Time Offsets in RTP Streams.
820// 0 1 2 3
821// 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
822// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
823// hdr |V=2|P| RC | PT=IJ=195 | length |
824// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
825// | inter-arrival jitter |
826// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
827// . .
828// . .
829// . .
830// | inter-arrival jitter |
831// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
832//
833// If present, this RTCP packet must be placed after a receiver report
834// (inside a compound RTCP packet), and MUST have the same value for RC
835// (reception report count) as the receiver report.
836
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000837int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000838RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000839 uint8_t* rtcpbuffer,
840 uint32_t& pos,
841 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000842{
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000843 if (_reportBlocks.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000844 {
845 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
846 return 0;
847 }
848
849 // sanity
850 if(pos + 8 >= IP_PACKET_SIZE)
851 {
852 return -2;
853 }
854 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000855 uint8_t RC = 1;
856 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
857 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000858
859 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000860 rtcpbuffer[pos++]=(uint8_t)0;
861 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000862
863 // Add inter-arrival jitter
864 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
865 jitterTransmissionTimeOffset);
866 pos += 4;
867 return 0;
868}
869
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000870int32_t
871RTCPSender::BuildPLI(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000872{
873 // sanity
874 if(pos + 12 >= IP_PACKET_SIZE)
875 {
876 return -2;
877 }
878 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000879 uint8_t FMT = 1;
880 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
881 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000882
883 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000884 rtcpbuffer[pos++]=(uint8_t)0;
885 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000886
887 // Add our own SSRC
888 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
889 pos += 4;
890
891 // Add the remote SSRC
892 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
893 pos += 4;
894 return 0;
895}
896
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000897int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
898 uint32_t& pos,
899 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000900 // sanity
901 if(pos + 20 >= IP_PACKET_SIZE) {
902 return -2;
903 }
904 if (!repeat) {
905 _sequenceNumberFIR++; // do not increase if repetition
906 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000907
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000908 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000909 uint8_t FMT = 4;
910 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
911 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000912
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000913 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000914 rtcpbuffer[pos++] = (uint8_t)0;
915 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000916
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000917 // Add our own SSRC
918 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
919 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000920
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000921 // RFC 5104 4.3.1.2. Semantics
922 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000923 rtcpbuffer[pos++] = (uint8_t)0;
924 rtcpbuffer[pos++] = (uint8_t)0;
925 rtcpbuffer[pos++] = (uint8_t)0;
926 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000927
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000928 // Additional Feedback Control Information (FCI)
929 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
930 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000931
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000932 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
933 rtcpbuffer[pos++] = (uint8_t)0;
934 rtcpbuffer[pos++] = (uint8_t)0;
935 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000936 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000937}
938
939/*
940 0 1 2 3
941 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
942 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
943 | First | Number | PictureID |
944 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
945*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000946int32_t
947RTCPSender::BuildSLI(uint8_t* rtcpbuffer, uint32_t& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000948{
949 // sanity
950 if(pos + 16 >= IP_PACKET_SIZE)
951 {
952 return -2;
953 }
954 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000955 uint8_t FMT = 2;
956 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
957 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000958
959 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000960 rtcpbuffer[pos++]=(uint8_t)0;
961 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000962
963 // Add our own SSRC
964 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
965 pos += 4;
966
967 // Add the remote SSRC
968 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
969 pos += 4;
970
971 // Add first, number & picture ID 6 bits
972 // first = 0, 13 - bits
973 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000974 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000975 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
976 pos += 4;
977 return 0;
978}
979
980/*
981 0 1 2 3
982 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
983 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
984 | PB |0| Payload Type| Native RPSI bit string |
985 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
986 | defined per codec ... | Padding (0) |
987 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
988*/
989/*
990* Note: not generic made for VP8
991*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000992int32_t
993RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
994 uint32_t& pos,
995 const uint64_t pictureID,
996 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +0000997{
998 // sanity
999 if(pos + 24 >= IP_PACKET_SIZE)
1000 {
1001 return -2;
1002 }
1003 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001004 uint8_t FMT = 3;
1005 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1006 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001007
1008 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001009 uint32_t bitsRequired = 7;
1010 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001011 while((pictureID>>bitsRequired) > 0)
1012 {
1013 bitsRequired += 7;
1014 bytesRequired++;
1015 }
1016
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001017 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001018 if(bytesRequired > 6)
1019 {
1020 size = 5;
1021 } else if(bytesRequired > 2)
1022 {
1023 size = 4;
1024 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001025 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001026 rtcpbuffer[pos++]=size;
1027
1028 // Add our own SSRC
1029 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1030 pos += 4;
1031
1032 // Add the remote SSRC
1033 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1034 pos += 4;
1035
1036 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001037 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001038 if(paddingBytes == 4)
1039 {
1040 paddingBytes = 0;
1041 }
1042 // add padding length in bits
1043 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1044 pos++;
1045
1046 // add payload type
1047 rtcpbuffer[pos] = payloadType;
1048 pos++;
1049
1050 // add picture ID
1051 for(int i = bytesRequired-1; i > 0; i--)
1052 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001053 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001054 pos++;
1055 }
1056 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001057 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001058 pos++;
1059
1060 // add padding
1061 for(int j = 0; j <paddingBytes; j++)
1062 {
1063 rtcpbuffer[pos] = 0;
1064 pos++;
1065 }
1066 return 0;
1067}
1068
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001069int32_t
1070RTCPSender::BuildREMB(uint8_t* rtcpbuffer, uint32_t& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001071{
1072 // sanity
1073 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1074 {
1075 return -2;
1076 }
1077 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001078 uint8_t FMT = 15;
1079 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1080 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001081
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001082 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001083 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1084
1085 // Add our own SSRC
1086 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1087 pos += 4;
1088
1089 // Remote SSRC must be 0
1090 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1091 pos += 4;
1092
1093 rtcpbuffer[pos++]='R';
1094 rtcpbuffer[pos++]='E';
1095 rtcpbuffer[pos++]='M';
1096 rtcpbuffer[pos++]='B';
1097
1098 rtcpbuffer[pos++] = _lengthRembSSRC;
1099 // 6 bit Exp
1100 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001101 uint8_t brExp = 0;
1102 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001103 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001104 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001105 {
1106 brExp = i;
1107 break;
1108 }
1109 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001110 const uint32_t brMantissa = (_rembBitrate >> brExp);
1111 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1112 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1113 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001114
1115 for (int i = 0; i < _lengthRembSSRC; i++)
1116 {
1117 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1118 pos += 4;
1119 }
edjee@google.com79b02892013-04-04 19:43:34 +00001120 TRACE_COUNTER1("webrtc_rtcp", "Remb", _rembBitrate);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001121 return 0;
1122}
1123
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001124void
1125RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001126{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001127 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001128 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001129}
1130
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001131int32_t
1132RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001133{
1134 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1135 // If the sender is an owner of the TMMBN -> send TMMBR
1136 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1137
niklase@google.com470e71d2011-07-07 08:21:25 +00001138 // get current bounding set from RTCP receiver
1139 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001140 // store in candidateSet, allocates one extra slot
1141 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001142
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001143 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1144 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1145 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001146 int32_t lengthOfBoundingSet
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001147 = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001148
1149 if(lengthOfBoundingSet > 0)
1150 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001151 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001152 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001153 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1154 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001155 {
1156 // do not send the same tuple
1157 return 0;
1158 }
1159 }
1160 if(!tmmbrOwner)
1161 {
1162 // use received bounding set as candidate set
1163 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001164 candidateSet->SetEntry(lengthOfBoundingSet,
1165 _tmmbr_Send,
1166 _packetOH_Send,
1167 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001168 int numCandidates = lengthOfBoundingSet+ 1;
1169
1170 // find bounding set
1171 TMMBRSet* boundingSet = NULL;
1172 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1173 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1174 {
1175 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1176 }
1177 if(!tmmbrOwner)
1178 {
1179 // did not enter bounding set, no meaning to send this request
1180 return 0;
1181 }
1182 }
1183 }
1184
1185 if(_tmmbr_Send)
1186 {
1187 // sanity
1188 if(pos + 20 >= IP_PACKET_SIZE)
1189 {
1190 return -2;
1191 }
1192 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001193 uint8_t FMT = 3;
1194 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1195 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001196
1197 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001198 rtcpbuffer[pos++]=(uint8_t)0;
1199 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001200
1201 // Add our own SSRC
1202 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1203 pos += 4;
1204
1205 // RFC 5104 4.2.1.2. Semantics
1206
1207 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001208 rtcpbuffer[pos++]=(uint8_t)0;
1209 rtcpbuffer[pos++]=(uint8_t)0;
1210 rtcpbuffer[pos++]=(uint8_t)0;
1211 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001212
1213 // Additional Feedback Control Information (FCI)
1214 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1215 pos += 4;
1216
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001217 uint32_t bitRate = _tmmbr_Send*1000;
1218 uint32_t mmbrExp = 0;
1219 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001220 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001221 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001222 {
1223 mmbrExp = i;
1224 break;
1225 }
1226 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001227 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001228
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001229 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1230 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1231 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1232 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001233 }
1234 return 0;
1235}
1236
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001237int32_t
1238RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001239{
1240 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1241 if(boundingSet == NULL)
1242 {
1243 return -1;
1244 }
1245 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001246 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001247 {
1248 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1249 return -2;
1250 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001251 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001252 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001253 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1254 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001255
1256 //Add length later
1257 int posLength = pos;
1258 pos++;
1259 pos++;
1260
1261 // Add our own SSRC
1262 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1263 pos += 4;
1264
1265 // RFC 5104 4.2.2.2. Semantics
1266
1267 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001268 rtcpbuffer[pos++]=(uint8_t)0;
1269 rtcpbuffer[pos++]=(uint8_t)0;
1270 rtcpbuffer[pos++]=(uint8_t)0;
1271 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001272
1273 // Additional Feedback Control Information (FCI)
1274 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001275 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001276 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001277 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001278 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001279 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001280 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1281 pos += 4;
1282
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001283 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1284 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001285 for(int i=0; i<64; i++)
1286 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001287 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001288 {
1289 mmbrExp = i;
1290 break;
1291 }
1292 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001293 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1294 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001295
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001296 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1297 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1298 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1299 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001300 numBoundingSet++;
1301 }
1302 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001303 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1304 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1305 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001306 return 0;
1307}
1308
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001309int32_t
1310RTCPSender::BuildAPP(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001311{
1312 // sanity
1313 if(_appData == NULL)
1314 {
1315 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1316 return -1;
1317 }
1318 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1319 {
1320 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1321 return -2;
1322 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001323 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001324
1325 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001326 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001327
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001328 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1329 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1330 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001331
1332 // Add our own SSRC
1333 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1334 pos += 4;
1335
1336 // Add our application name
1337 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1338 pos += 4;
1339
1340 // Add the data
1341 memcpy(rtcpbuffer +pos, _appData,_appLength);
1342 pos += _appLength;
1343 return 0;
1344}
1345
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001346int32_t
1347RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
1348 uint32_t& pos,
1349 const int32_t nackSize,
1350 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001351 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001352{
1353 // sanity
1354 if(pos + 16 >= IP_PACKET_SIZE)
1355 {
1356 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1357 return -2;
1358 }
1359
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001360 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001361 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001362 uint8_t FMT = 1;
1363 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1364 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001365
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001366 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001367 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001368 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001369
1370 // Add our own SSRC
1371 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1372 pos += 4;
1373
1374 // Add the remote SSRC
1375 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1376 pos += 4;
1377
1378 // add the list
1379 int i = 0;
1380 int numOfNackFields = 0;
edjee@google.com79b02892013-04-04 19:43:34 +00001381 NACKStringBuilder stringBuilder;
stefan@webrtc.orga2710702013-03-05 09:02:06 +00001382 while (nackSize > i && numOfNackFields < kRtcpMaxNackFields)
niklase@google.com470e71d2011-07-07 08:21:25 +00001383 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001384 uint16_t nack = nackList[i];
niklase@google.com470e71d2011-07-07 08:21:25 +00001385 // put dow our sequence number
1386 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, nack);
1387 pos += 2;
edjee@google.com79b02892013-04-04 19:43:34 +00001388 stringBuilder.PushNACK(nack);
niklase@google.com470e71d2011-07-07 08:21:25 +00001389
1390 i++;
1391 numOfNackFields++;
1392 if(nackSize > i)
1393 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001394 bool moreThan16Away = (uint16_t(nack+16) < nackList[i])?true: false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001395 if(!moreThan16Away)
1396 {
1397 // check for a wrap
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001398 if(uint16_t(nack+16) > 0xff00 && nackList[i] < 0x0fff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001399 {
1400 // wrap
1401 moreThan16Away = true;
1402 }
1403 }
1404 if(moreThan16Away)
1405 {
1406 // next is more than 16 away
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001407 rtcpbuffer[pos++]=(uint8_t)0;
1408 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001409 } else
1410 {
1411 // build our bitmask
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001412 uint16_t bitmask = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001413
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001414 bool within16Away = (uint16_t(nack+16) > nackList[i])?true: false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001415 if(within16Away)
1416 {
1417 // check for a wrap
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001418 if(uint16_t(nack+16) > 0xff00 && nackList[i] < 0x0fff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001419 {
1420 // wrap
1421 within16Away = false;
1422 }
1423 }
1424
1425 while( nackSize > i && within16Away)
1426 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001427 int16_t shift = (nackList[i]-nack)-1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001428 assert(!(shift > 15) && !(shift < 0));
1429
1430 bitmask += (1<< shift);
edjee@google.com79b02892013-04-04 19:43:34 +00001431 stringBuilder.PushNACK(nackList[i]);
niklase@google.com470e71d2011-07-07 08:21:25 +00001432 i++;
1433 if(nackSize > i)
1434 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001435 within16Away = (uint16_t(nack+16) > nackList[i])?true: false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001436 if(within16Away)
1437 {
1438 // check for a wrap
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001439 if(uint16_t(nack+16) > 0xff00 && nackList[i] < 0x0fff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001440 {
1441 // wrap
1442 within16Away = false;
1443 }
1444 }
1445 }
1446 }
1447 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, bitmask);
1448 pos += 2;
1449 }
1450 // sanity do we have room from one more 4 byte block?
1451 if(pos + 4 >= IP_PACKET_SIZE)
1452 {
1453 return -2;
1454 }
1455 } else
1456 {
1457 // no more in the list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001458 rtcpbuffer[pos++]=(uint8_t)0;
1459 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001460 }
1461 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001462 rtcpbuffer[nackSizePos]=(uint8_t)(2+numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001463 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001464 return 0;
1465}
1466
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001467int32_t
1468RTCPSender::BuildBYE(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001469{
1470 // sanity
1471 if(pos + 8 >= IP_PACKET_SIZE)
1472 {
1473 return -2;
1474 }
1475 if(_includeCSRCs)
1476 {
1477 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001478 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1479 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001480
1481 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001482 rtcpbuffer[pos++]=(uint8_t)0;
1483 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001484
1485 // Add our own SSRC
1486 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1487 pos += 4;
1488
1489 // add CSRCs
1490 for(int i = 0; i < _CSRCs; i++)
1491 {
1492 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1493 pos += 4;
1494 }
1495 } else
1496 {
1497 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001498 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1499 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001500
1501 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001502 rtcpbuffer[pos++]=(uint8_t)0;
1503 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001504
1505 // Add our own SSRC
1506 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1507 pos += 4;
1508 }
1509 return 0;
1510}
1511
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001512int32_t
1513RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001514{
1515 // sanity
1516 if(pos + 44 >= IP_PACKET_SIZE)
1517 {
1518 return -2;
1519 }
1520
1521 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001522 rtcpbuffer[pos++]=(uint8_t)0x80;
1523 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001524
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001525 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001526
1527 // handle length later on
1528 pos++;
1529 pos++;
1530
1531 // Add our own SSRC
1532 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1533 pos += 4;
1534
1535 // Add a VoIP metrics block
1536 rtcpbuffer[pos++]=7;
1537 rtcpbuffer[pos++]=0;
1538 rtcpbuffer[pos++]=0;
1539 rtcpbuffer[pos++]=8;
1540
1541 // Add the remote SSRC
1542 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1543 pos += 4;
1544
1545 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1546 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1547 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1548 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1549
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001550 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1551 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1552 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1553 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001554
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001555 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1556 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1557 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1558 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001559
1560 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1561 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1562 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1563 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1564
1565 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1566 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1567 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1568 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1569
1570 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1571 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001572 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1573 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001574
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001575 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1576 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1577 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1578 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001579
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001580 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1581 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001582 return 0;
1583}
1584
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001585int32_t
1586RTCPSender::SendRTCP(const uint32_t packetTypeFlags,
1587 const int32_t nackSize, // NACK
1588 const uint16_t* nackList, // NACK
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001589 const bool repeat, // FIR
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001590 const uint64_t pictureID) // SLI & RPSI
niklase@google.com470e71d2011-07-07 08:21:25 +00001591{
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001592 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1593 uint32_t pos = 0;
1594 uint8_t rtcpbuffer[IP_PACKET_SIZE];
niklase@google.com470e71d2011-07-07 08:21:25 +00001595
niklase@google.com470e71d2011-07-07 08:21:25 +00001596 do // only to be able to use break :) (and the critsect must be inside its own scope)
1597 {
1598 // collect the received information
1599 RTCPReportBlock received;
1600 bool hasReceived = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001601 uint32_t NTPsec = 0;
1602 uint32_t NTPfrac = 0;
xians@webrtc.org8738d272011-11-25 13:43:53 +00001603 bool rtcpCompound = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001604 uint32_t jitterTransmissionOffset = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001605
xians@webrtc.org8738d272011-11-25 13:43:53 +00001606 {
1607 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1608 if(_method == kRtcpOff)
1609 {
1610 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1611 "%s invalid state", __FUNCTION__);
1612 return -1;
1613 }
1614 rtcpCompound = (_method == kRtcpCompound) ? true : false;
1615 }
1616
1617 if (rtcpCompound ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001618 rtcpPacketTypeFlags & kRtcpReport ||
1619 rtcpPacketTypeFlags & kRtcpSr ||
1620 rtcpPacketTypeFlags & kRtcpRr)
1621 {
1622 // get statistics from our RTPreceiver outside critsect
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001623 if(_rtpRtcp.ReportBlockStatistics(&received.fractionLost,
1624 &received.cumulativeLost,
1625 &received.extendedHighSeqNum,
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001626 &received.jitter,
1627 &jitterTransmissionOffset) == 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001628 {
1629 hasReceived = true;
1630
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001631 uint32_t lastReceivedRRNTPsecs = 0;
1632 uint32_t lastReceivedRRNTPfrac = 0;
1633 uint32_t remoteSR = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001634
1635 // ok even if we have not received a SR, we will send 0 in that case
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001636 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1637 lastReceivedRRNTPfrac,
1638 remoteSR);
niklase@google.com470e71d2011-07-07 08:21:25 +00001639
1640 // get our NTP as late as possible to avoid a race
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001641 _clock->CurrentNtp(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001642
1643 // Delay since last received report
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001644 uint32_t delaySinceLastReceivedSR = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001645 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
1646 {
1647 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001648 uint32_t now=NTPsec&0x0000FFFF;
niklase@google.com470e71d2011-07-07 08:21:25 +00001649 now <<=16;
1650 now += (NTPfrac&0xffff0000)>>16;
1651
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001652 uint32_t receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
niklase@google.com470e71d2011-07-07 08:21:25 +00001653 receiveTime <<=16;
1654 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1655
1656 delaySinceLastReceivedSR = now-receiveTime;
1657 }
1658 received.delaySinceLastSR = delaySinceLastReceivedSR;
1659 received.lastSR = remoteSR;
1660 } else
1661 {
1662 // we need to send our NTP even if we dont have received any reports
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001663 _clock->CurrentNtp(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001664 }
1665 }
1666
1667 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1668
1669 if(_TMMBR ) // attach TMMBR to send and receive reports
1670 {
1671 rtcpPacketTypeFlags |= kRtcpTmmbr;
1672 }
1673 if(_appSend)
1674 {
1675 rtcpPacketTypeFlags |= kRtcpApp;
1676 _appSend = false;
1677 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001678 if(_REMB && _sendREMB)
1679 {
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +00001680 // Always attach REMB to SR if that is configured. Note that REMB is
1681 // only sent on one of the RTP modules in the REMB group.
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001682 rtcpPacketTypeFlags |= kRtcpRemb;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001683 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001684 if(_xrSendVoIPMetric)
1685 {
1686 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1687 _xrSendVoIPMetric = false;
1688 }
1689 if(_sendTMMBN) // set when having received a TMMBR
1690 {
1691 rtcpPacketTypeFlags |= kRtcpTmmbn;
1692 _sendTMMBN = false;
1693 }
1694
1695 if(_method == kRtcpCompound)
1696 {
1697 if(_sending)
1698 {
1699 rtcpPacketTypeFlags |= kRtcpSr;
1700 } else
1701 {
1702 rtcpPacketTypeFlags |= kRtcpRr;
1703 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001704 if (_IJ && hasReceived)
1705 {
1706 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1707 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001708 } else if(_method == kRtcpNonCompound)
1709 {
1710 if(rtcpPacketTypeFlags & kRtcpReport)
1711 {
1712 if(_sending)
1713 {
1714 rtcpPacketTypeFlags |= kRtcpSr;
1715 } else
1716 {
1717 rtcpPacketTypeFlags |= kRtcpRr;
1718 }
1719 }
1720 }
1721 if( rtcpPacketTypeFlags & kRtcpRr ||
1722 rtcpPacketTypeFlags & kRtcpSr)
1723 {
1724 // generate next time to send a RTCP report
1725 // seeded from RTP constructor
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001726 int32_t random = rand() % 1000;
1727 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
niklase@google.com470e71d2011-07-07 08:21:25 +00001728
1729 if(_audio)
1730 {
1731 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
1732 }else
1733 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001734 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
niklase@google.com470e71d2011-07-07 08:21:25 +00001735 if(_sending)
1736 {
1737 // calc bw for video 360/sendBW in kbit/s
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001738 uint32_t sendBitrateKbit = 0;
1739 uint32_t videoRate = 0;
1740 uint32_t fecRate = 0;
1741 uint32_t nackRate = 0;
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001742 _rtpRtcp.BitrateSent(&sendBitrateKbit,
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001743 &videoRate,
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001744 &fecRate,
1745 &nackRate);
1746 sendBitrateKbit /= 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001747 if(sendBitrateKbit != 0)
1748 {
1749 minIntervalMs = 360000/sendBitrateKbit;
1750 }
1751 }
1752 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1753 {
1754 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1755 }
1756 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1757 }
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001758 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
niklase@google.com470e71d2011-07-07 08:21:25 +00001759 }
1760
1761 // if the data does not fitt in the packet we fill it as much as possible
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001762 int32_t buildVal = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001763
1764 if(rtcpPacketTypeFlags & kRtcpSr)
1765 {
1766 if(hasReceived)
1767 {
1768 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
1769 } else
1770 {
1771 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac);
1772 }
1773 if(buildVal == -1)
1774 {
1775 return -1; // error
1776
1777 }else if(buildVal == -2)
1778 {
1779 break; // out of buffer
1780 }
1781 buildVal = BuildSDEC(rtcpbuffer, pos);
1782 if(buildVal == -1)
1783 {
1784 return -1; // error
1785
1786 }else if(buildVal == -2)
1787 {
1788 break; // out of buffer
1789 }
1790
1791 }else if(rtcpPacketTypeFlags & kRtcpRr)
1792 {
1793 if(hasReceived)
1794 {
1795 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
1796 }else
1797 {
1798 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
1799 }
1800 if(buildVal == -1)
1801 {
1802 return -1; // error
1803
1804 }else if(buildVal == -2)
1805 {
1806 break; // out of buffer
1807 }
1808 // only of set
1809 if(_CNAME[0] != 0)
1810 {
1811 buildVal = BuildSDEC(rtcpbuffer, pos);
1812 if(buildVal == -1)
1813 {
1814 return -1; // error
1815 }
1816 }
1817 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001818 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1819 {
1820 // If present, this RTCP packet must be placed after a
1821 // receiver report.
1822 buildVal = BuildExtendedJitterReport(rtcpbuffer,
1823 pos,
1824 jitterTransmissionOffset);
1825 if(buildVal == -1)
1826 {
1827 return -1; // error
1828 }
1829 else if(buildVal == -2)
1830 {
1831 break; // out of buffer
1832 }
1833 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001834 if(rtcpPacketTypeFlags & kRtcpPli)
1835 {
1836 buildVal = BuildPLI(rtcpbuffer, pos);
1837 if(buildVal == -1)
1838 {
1839 return -1; // error
1840
1841 }else if(buildVal == -2)
1842 {
1843 break; // out of buffer
1844 }
edjee@google.com79b02892013-04-04 19:43:34 +00001845 TRACE_EVENT_INSTANT1("webrtc_rtcp", "SendRTCP", "type", "pli");
1846 _pliCount++;
1847 TRACE_COUNTER1("webrtc_rtcp", "PLI Count", _pliCount);
niklase@google.com470e71d2011-07-07 08:21:25 +00001848 }
1849 if(rtcpPacketTypeFlags & kRtcpFir)
1850 {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001851 buildVal = BuildFIR(rtcpbuffer, pos, repeat);
niklase@google.com470e71d2011-07-07 08:21:25 +00001852 if(buildVal == -1)
1853 {
1854 return -1; // error
1855
1856 }else if(buildVal == -2)
1857 {
1858 break; // out of buffer
1859 }
edjee@google.com79b02892013-04-04 19:43:34 +00001860 TRACE_EVENT_INSTANT1("webrtc_rtcp", "SendRTCP", "type", "fir");
1861 _fullIntraRequestCount++;
1862 TRACE_COUNTER1("webrtc_rtcp", "FIR Count", _fullIntraRequestCount);
niklase@google.com470e71d2011-07-07 08:21:25 +00001863 }
1864 if(rtcpPacketTypeFlags & kRtcpSli)
1865 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001866 buildVal = BuildSLI(rtcpbuffer, pos, (uint8_t)pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +00001867 if(buildVal == -1)
1868 {
1869 return -1; // error
1870
1871 }else if(buildVal == -2)
1872 {
1873 break; // out of buffer
1874 }
1875 }
1876 if(rtcpPacketTypeFlags & kRtcpRpsi)
1877 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001878 const int8_t payloadType = _rtpRtcp.SendPayloadType();
niklase@google.com470e71d2011-07-07 08:21:25 +00001879 if(payloadType == -1)
1880 {
1881 return -1;
1882 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001883 buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (uint8_t)payloadType);
niklase@google.com470e71d2011-07-07 08:21:25 +00001884 if(buildVal == -1)
1885 {
1886 return -1; // error
1887
1888 }else if(buildVal == -2)
1889 {
1890 break; // out of buffer
1891 }
1892 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001893 if(rtcpPacketTypeFlags & kRtcpRemb)
1894 {
1895 buildVal = BuildREMB(rtcpbuffer, pos);
1896 if(buildVal == -1)
1897 {
1898 return -1; // error
1899
1900 }else if(buildVal == -2)
1901 {
1902 break; // out of buffer
1903 }
edjee@google.com79b02892013-04-04 19:43:34 +00001904 TRACE_EVENT_INSTANT2("webrtc_rtcp", "SendRTCP", "type", "remb",
1905 "bitrate", _rembBitrate);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001906 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001907 if(rtcpPacketTypeFlags & kRtcpBye)
1908 {
1909 buildVal = BuildBYE(rtcpbuffer, pos);
1910 if(buildVal == -1)
1911 {
1912 return -1; // error
1913
1914 }else if(buildVal == -2)
1915 {
1916 break; // out of buffer
1917 }
1918 }
1919 if(rtcpPacketTypeFlags & kRtcpApp)
1920 {
1921 buildVal = BuildAPP(rtcpbuffer, pos);
1922 if(buildVal == -1)
1923 {
1924 return -1; // error
1925
1926 }else if(buildVal == -2)
1927 {
1928 break; // out of buffer
1929 }
1930 }
1931 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1932 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001933 buildVal = BuildTMMBR(rtcpbuffer, pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001934 if(buildVal == -1)
1935 {
1936 return -1; // error
1937
1938 }else if(buildVal == -2)
1939 {
1940 break; // out of buffer
1941 }
1942 }
1943 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1944 {
1945 buildVal = BuildTMMBN(rtcpbuffer, pos);
1946 if(buildVal == -1)
1947 {
1948 return -1; // error
1949
1950 }else if(buildVal == -2)
1951 {
1952 break; // out of buffer
1953 }
1954 }
1955 if(rtcpPacketTypeFlags & kRtcpNack)
1956 {
edjee@google.com79b02892013-04-04 19:43:34 +00001957 std::string nackString;
1958 buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList,
1959 &nackString);
niklase@google.com470e71d2011-07-07 08:21:25 +00001960 if(buildVal == -1)
1961 {
1962 return -1; // error
1963
1964 }else if(buildVal == -2)
1965 {
1966 break; // out of buffer
1967 }
edjee@google.com79b02892013-04-04 19:43:34 +00001968 TRACE_EVENT_INSTANT2("webrtc_rtcp", "SendRTCP", "type", "nack",
1969 "list", TRACE_STR_COPY(nackString.c_str()));
1970 _nackCount++;
1971 TRACE_COUNTER1("webrtc_rtcp", "Nacks", _nackCount);
niklase@google.com470e71d2011-07-07 08:21:25 +00001972 }
1973 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1974 {
1975 buildVal = BuildVoIPMetric(rtcpbuffer, pos);
1976 if(buildVal == -1)
1977 {
1978 return -1; // error
1979
1980 }else if(buildVal == -2)
1981 {
1982 break; // out of buffer
1983 }
1984 }
1985 }while (false);
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001986 // Sanity don't send empty packets.
1987 if (pos == 0)
1988 {
1989 return -1;
1990 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001991 return SendToNetwork(rtcpbuffer, (uint16_t)pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001992}
1993
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001994int32_t
1995RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
1996 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001997{
1998 CriticalSectionScoped lock(_criticalSectionTransport);
1999 if(_cbTransport)
2000 {
2001 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
2002 {
2003 return 0;
2004 }
2005 }
2006 return -1;
2007}
2008
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002009int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002010RTCPSender::SetCSRCStatus(const bool include)
2011{
2012 _includeCSRCs = include;
2013 return 0;
2014}
2015
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002016int32_t
2017RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
2018 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00002019{
2020 if(arrLength > kRtpCsrcSize)
2021 {
2022 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2023 assert(false);
2024 return -1;
2025 }
2026
2027 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2028
2029 for(int i = 0; i < arrLength;i++)
2030 {
2031 _CSRC[i] = arrOfCSRC[i];
2032 }
2033 _CSRCs = arrLength;
2034 return 0;
2035}
2036
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002037int32_t
2038RTCPSender::SetApplicationSpecificData(const uint8_t subType,
2039 const uint32_t name,
2040 const uint8_t* data,
2041 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002042{
2043 if(length %4 != 0)
2044 {
2045 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2046 return -1;
2047 }
2048 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2049
2050 if(_appData)
2051 {
2052 delete [] _appData;
2053 }
2054
2055 _appSend = true;
2056 _appSubType = subType;
2057 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002058 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002059 _appLength = length;
2060 memcpy(_appData, data, length);
2061 return 0;
2062}
2063
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002064int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002065RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2066{
2067 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2068 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2069
2070 _xrSendVoIPMetric = true;
2071 return 0;
2072}
2073
2074// called under critsect _criticalSectionRTCPSender
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002075int32_t RTCPSender::AddReportBlocks(uint8_t* rtcpbuffer,
2076 uint32_t& pos,
2077 uint8_t& numberOfReportBlocks,
2078 const RTCPReportBlock* received,
2079 const uint32_t NTPsec,
2080 const uint32_t NTPfrac) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002081 // sanity one block
2082 if(pos + 24 >= IP_PACKET_SIZE) {
2083 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2084 "%s invalid argument", __FUNCTION__);
2085 return -1;
2086 }
2087 numberOfReportBlocks = _reportBlocks.size();
2088 if (received) {
2089 // add our multiple RR to numberOfReportBlocks
2090 numberOfReportBlocks++;
2091 }
2092 if (received) {
2093 // answer to the one that sends to me
2094 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac);
2095
2096 // Remote SSRC
2097 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
2098 pos += 4;
2099
2100 // fraction lost
2101 rtcpbuffer[pos++]=received->fractionLost;
2102
2103 // cumulative loss
2104 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2105 received->cumulativeLost);
2106 pos += 3;
2107 // extended highest seq_no, contain the highest sequence number received
2108 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2109 received->extendedHighSeqNum);
2110 pos += 4;
2111
2112 //Jitter
2113 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
2114 pos += 4;
2115
2116 // Last SR timestamp, our NTP time when we received the last report
2117 // This is the value that we read from the send report packet not when we
2118 // received it...
2119 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
2120 pos += 4;
2121
2122 // Delay since last received report,time since we received the report
2123 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2124 received->delaySinceLastSR);
2125 pos += 4;
2126 }
2127 if ((pos + _reportBlocks.size() * 24) >= IP_PACKET_SIZE) {
2128 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2129 "%s invalid argument", __FUNCTION__);
2130 return -1;
2131 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002132 std::map<uint32_t, RTCPReportBlock*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002133 _reportBlocks.begin();
2134
2135 for (; it != _reportBlocks.end(); it++) {
2136 // we can have multiple report block in a conference
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002137 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002138 RTCPReportBlock* reportBlock = it->second;
2139 if (reportBlock) {
2140 // Remote SSRC
2141 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
2142 pos += 4;
2143
2144 // fraction lost
2145 rtcpbuffer[pos++] = reportBlock->fractionLost;
2146
2147 // cumulative loss
2148 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2149 reportBlock->cumulativeLost);
2150 pos += 3;
2151
2152 // extended highest seq_no, contain the highest sequence number received
2153 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2154 reportBlock->extendedHighSeqNum);
2155 pos += 4;
2156
2157 //Jitter
2158 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2159 reportBlock->jitter);
2160 pos += 4;
2161
2162 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2163 reportBlock->lastSR);
2164 pos += 4;
2165
2166 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2167 reportBlock->delaySinceLastSR);
2168 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002169 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002170 }
2171 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00002172}
2173
2174// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002175int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002176RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002177 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002178{
2179 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2180
2181 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2182 {
2183 _sendTMMBN = true;
2184 return 0;
2185 }
2186 return -1;
2187}
niklase@google.com470e71d2011-07-07 08:21:25 +00002188} // namespace webrtc