blob: 67e34def32cb1a36818fb19de9ca7686a8c1c6d3 [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
andresp@webrtc.org523f9372013-04-11 11:30:39 +000013#include <algorithm> // min
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000014#include <cassert> // assert
15#include <cstdlib> // rand
16#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000017
niklase@google.com470e71d2011-07-07 08:21:25 +000018#include "common_types.h"
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000019#include "modules/rtp_rtcp/source/rtp_rtcp_impl.h"
20#include "system_wrappers/interface/critical_section_wrapper.h"
21#include "system_wrappers/interface/trace.h"
edjee@google.com79b02892013-04-04 19:43:34 +000022#include "system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000023
niklase@google.com470e71d2011-07-07 08:21:25 +000024namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000025
26using RTCPUtility::RTCPCnameInformation;
27
edjee@google.com79b02892013-04-04 19:43:34 +000028NACKStringBuilder::NACKStringBuilder() :
29 _stream(""), _count(0), _consecutive(false)
30{
31 // Empty.
32}
33
pbos@webrtc.org2f446732013-04-08 11:08:41 +000034void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000035{
36 if (_count == 0)
37 {
38 _stream << nack;
39 } else if (nack == _prevNack + 1)
40 {
41 _consecutive = true;
42 } else
43 {
44 if (_consecutive)
45 {
46 _stream << "-" << _prevNack;
47 _consecutive = false;
48 }
49 _stream << "," << nack;
50 }
51 _count++;
52 _prevNack = nack;
53}
54
55std::string NACKStringBuilder::GetResult()
56{
57 if (_consecutive)
58 {
59 _stream << "-" << _prevNack;
60 _consecutive = false;
61 }
62 return _stream.str();
63}
64
pbos@webrtc.org2f446732013-04-08 11:08:41 +000065RTCPSender::RTCPSender(const int32_t id,
niklase@google.com470e71d2011-07-07 08:21:25 +000066 const bool audio,
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000067 Clock* clock,
pwestin@webrtc.org741da942011-09-20 13:52:04 +000068 ModuleRtpRtcpImpl* owner) :
niklase@google.com470e71d2011-07-07 08:21:25 +000069 _id(id),
70 _audio(audio),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000071 _clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000072 _method(kRtcpOff),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000073 _rtpRtcp(*owner),
henrike@webrtc.org65573f22011-12-13 19:17:27 +000074 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000075 _cbTransport(NULL),
76
henrike@webrtc.org65573f22011-12-13 19:17:27 +000077 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000078 _usingNack(false),
79 _sending(false),
80 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000081 _REMB(false),
82 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000083 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +000084 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000085 _nextTimeToSendRTCP(0),
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000086 start_timestamp_(0),
87 last_rtp_timestamp_(0),
88 last_frame_capture_time_ms_(-1),
niklase@google.com470e71d2011-07-07 08:21:25 +000089 _SSRC(0),
90 _remoteSSRC(0),
91 _CNAME(),
92 _reportBlocks(),
93 _csrcCNAMEs(),
94
stefan@webrtc.org7da34592013-04-09 14:56:29 +000095 _cameraDelayMS(0),
96
niklase@google.com470e71d2011-07-07 08:21:25 +000097 _lastSendReport(),
98 _lastRTCPTime(),
99
100 _CSRCs(0),
101 _CSRC(),
102 _includeCSRCs(true),
103
104 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000105
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000106 _lengthRembSSRC(0),
107 _sizeRembSSRC(0),
108 _rembSSRC(NULL),
109 _rembBitrate(0),
110
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000111 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000112 _tmmbr_Send(0),
113 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000114
115 _appSend(false),
116 _appSubType(0),
117 _appName(),
118 _appData(NULL),
119 _appLength(0),
120 _xrSendVoIPMetric(false),
edjee@google.com79b02892013-04-04 19:43:34 +0000121 _xrVoIPMetric(),
122 _nackCount(0),
123 _pliCount(0),
124 _fullIntraRequestCount(0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000125{
126 memset(_CNAME, 0, sizeof(_CNAME));
127 memset(_lastSendReport, 0, sizeof(_lastSendReport));
128 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
129
130 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
131}
132
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000133RTCPSender::~RTCPSender() {
134 delete [] _rembSSRC;
135 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000136
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000137 while (!_reportBlocks.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000138 std::map<uint32_t, RTCPReportBlock*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000139 _reportBlocks.begin();
140 delete it->second;
141 _reportBlocks.erase(it);
142 }
143 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000144 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000145 _csrcCNAMEs.begin();
146 delete it->second;
147 _csrcCNAMEs.erase(it);
148 }
149 delete _criticalSectionTransport;
150 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000151
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000152 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000153}
154
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000155int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000156RTCPSender::Init()
157{
158 CriticalSectionScoped lock(_criticalSectionRTCPSender);
159
160 _method = kRtcpOff;
161 _cbTransport = NULL;
162 _usingNack = false;
163 _sending = false;
164 _sendTMMBN = false;
165 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000166 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000167 _REMB = false;
168 _sendREMB = false;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000169 last_rtp_timestamp_ = 0;
170 last_frame_capture_time_ms_ = -1;
171 start_timestamp_ = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000172 _SSRC = 0;
173 _remoteSSRC = 0;
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000174 _cameraDelayMS = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000175 _sequenceNumberFIR = 0;
176 _tmmbr_Send = 0;
177 _packetOH_Send = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000178 _nextTimeToSendRTCP = 0;
179 _CSRCs = 0;
180 _appSend = false;
181 _appSubType = 0;
182
183 if(_appData)
184 {
185 delete [] _appData;
186 _appData = NULL;
187 }
188 _appLength = 0;
189
190 _xrSendVoIPMetric = false;
191
192 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
193 memset(_CNAME, 0, sizeof(_CNAME));
194 memset(_lastSendReport, 0, sizeof(_lastSendReport));
195 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
edjee@google.com79b02892013-04-04 19:43:34 +0000196
197 _nackCount = 0;
198 _pliCount = 0;
199 _fullIntraRequestCount = 0;
200
niklase@google.com470e71d2011-07-07 08:21:25 +0000201 return 0;
202}
203
204void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000205RTCPSender::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +0000206{
207 _id = id;
208}
209
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000210int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000211RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
212{
213 CriticalSectionScoped lock(_criticalSectionTransport);
214 _cbTransport = outgoingTransport;
215 return 0;
216}
217
218RTCPMethod
219RTCPSender::Status() const
220{
221 CriticalSectionScoped lock(_criticalSectionRTCPSender);
222 return _method;
223}
224
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000225int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000226RTCPSender::SetRTCPStatus(const RTCPMethod method)
227{
228 CriticalSectionScoped lock(_criticalSectionRTCPSender);
229 if(method != kRtcpOff)
230 {
231 if(_audio)
232 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000233 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000234 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000235 } else
236 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000237 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000238 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000239 }
240 }
241 _method = method;
242 return 0;
243}
244
245bool
246RTCPSender::Sending() const
247{
248 CriticalSectionScoped lock(_criticalSectionRTCPSender);
249 return _sending;
250}
251
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000252int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000253RTCPSender::SetSendingStatus(const bool sending)
254{
255 bool sendRTCPBye = false;
256 {
257 CriticalSectionScoped lock(_criticalSectionRTCPSender);
258
259 if(_method != kRtcpOff)
260 {
261 if(sending == false && _sending == true)
262 {
263 // Trigger RTCP bye
264 sendRTCPBye = true;
265 }
266 }
267 _sending = sending;
268 }
269 if(sendRTCPBye)
270 {
271 return SendRTCP(kRtcpBye);
272 }
273 return 0;
274}
275
276bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000277RTCPSender::REMB() const
278{
279 CriticalSectionScoped lock(_criticalSectionRTCPSender);
280 return _REMB;
281}
282
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000283int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000284RTCPSender::SetREMBStatus(const bool enable)
285{
286 CriticalSectionScoped lock(_criticalSectionRTCPSender);
287 _REMB = enable;
288 return 0;
289}
290
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000291int32_t
292RTCPSender::SetREMBData(const uint32_t bitrate,
293 const uint8_t numberOfSSRC,
294 const uint32_t* SSRC)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000295{
296 CriticalSectionScoped lock(_criticalSectionRTCPSender);
297 _rembBitrate = bitrate;
298
299 if(_sizeRembSSRC < numberOfSSRC)
300 {
301 delete [] _rembSSRC;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000302 _rembSSRC = new uint32_t[numberOfSSRC];
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000303 _sizeRembSSRC = numberOfSSRC;
304 }
305
306 _lengthRembSSRC = numberOfSSRC;
307 for (int i = 0; i < numberOfSSRC; i++)
308 {
309 _rembSSRC[i] = SSRC[i];
310 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000311 _sendREMB = true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000312 return 0;
313}
314
315bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000316RTCPSender::TMMBR() const
317{
318 CriticalSectionScoped lock(_criticalSectionRTCPSender);
319 return _TMMBR;
320}
321
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000322int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000323RTCPSender::SetTMMBRStatus(const bool enable)
324{
325 CriticalSectionScoped lock(_criticalSectionRTCPSender);
326 _TMMBR = enable;
327 return 0;
328}
329
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000330bool
331RTCPSender::IJ() const
332{
333 CriticalSectionScoped lock(_criticalSectionRTCPSender);
334 return _IJ;
335}
336
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000337int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000338RTCPSender::SetIJStatus(const bool enable)
339{
340 CriticalSectionScoped lock(_criticalSectionRTCPSender);
341 _IJ = enable;
342 return 0;
343}
344
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000345void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
346 start_timestamp_ = start_timestamp;
347}
348
349void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
350 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000351 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000352 last_rtp_timestamp_ = rtp_timestamp;
353 if (capture_time_ms < 0) {
354 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000355 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000356 } else {
357 last_frame_capture_time_ms_ = capture_time_ms;
358 }
359}
360
niklase@google.com470e71d2011-07-07 08:21:25 +0000361void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000362RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000363{
364 CriticalSectionScoped lock(_criticalSectionRTCPSender);
365
366 if(_SSRC != 0)
367 {
368 // not first SetSSRC, probably due to a collision
369 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000370 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000371 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000372 }
373 _SSRC = ssrc;
374}
375
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000376int32_t
377RTCPSender::SetRemoteSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000378{
379 CriticalSectionScoped lock(_criticalSectionRTCPSender);
380 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000381 return 0;
382}
383
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000384int32_t
385RTCPSender::SetCameraDelay(const int32_t delayMS)
386{
387 CriticalSectionScoped lock(_criticalSectionRTCPSender);
388 if(delayMS > 1000 || delayMS < -1000)
389 {
390 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
391 return -1;
392 }
393 _cameraDelayMS = delayMS;
394 return 0;
395}
396
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000397int32_t RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000398 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000399 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000400 cName[RTCP_CNAME_SIZE - 1] = 0;
401 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000402 return 0;
403}
404
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000405int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000406 if (!cName)
407 return -1;
408
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000409 CriticalSectionScoped lock(_criticalSectionRTCPSender);
410 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
411 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
412 return 0;
413}
414
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000415int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
416 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000417 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000418 CriticalSectionScoped lock(_criticalSectionRTCPSender);
419 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
420 return -1;
421 }
422 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000423 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
424 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000425 _csrcCNAMEs[SSRC] = ptr;
426 return 0;
427}
428
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000429int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000430 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000431 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000432 _csrcCNAMEs.find(SSRC);
433
434 if (it == _csrcCNAMEs.end()) {
435 return -1;
436 }
437 delete it->second;
438 _csrcCNAMEs.erase(it);
439 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000440}
441
442bool
443RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
444{
445/*
446 For audio we use a fix 5 sec interval
447
448 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
449 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
450
451
452From RFC 3550
453
454 MAX RTCP BW is 5% if the session BW
455 A send report is approximately 65 bytes inc CNAME
456 A report report is approximately 28 bytes
457
458 The RECOMMENDED value for the reduced minimum in seconds is 360
459 divided by the session bandwidth in kilobits/second. This minimum
460 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
461
462 If the participant has not yet sent an RTCP packet (the variable
463 initial is true), the constant Tmin is set to 2.5 seconds, else it
464 is set to 5 seconds.
465
466 The interval between RTCP packets is varied randomly over the
467 range [0.5,1.5] times the calculated interval to avoid unintended
468 synchronization of all participants
469
470 if we send
471 If the participant is a sender (we_sent true), the constant C is
472 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
473 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
474 number of senders.
475
476 if we receive only
477 If we_sent is not true, the constant C is set
478 to the average RTCP packet size divided by 75% of the RTCP
479 bandwidth. The constant n is set to the number of receivers
480 (members - senders). If the number of senders is greater than
481 25%, senders and receivers are treated together.
482
483 reconsideration NOT required for peer-to-peer
484 "timer reconsideration" is
485 employed. This algorithm implements a simple back-off mechanism
486 which causes users to hold back RTCP packet transmission if the
487 group sizes are increasing.
488
489 n = number of members
490 C = avg_size/(rtcpBW/4)
491
492 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
493
494 4. The calculated interval T is set to a number uniformly distributed
495 between 0.5 and 1.5 times the deterministic calculated interval.
496
497 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
498 for the fact that the timer reconsideration algorithm converges to
499 a value of the RTCP bandwidth below the intended average
500*/
501
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000502 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000503
504 CriticalSectionScoped lock(_criticalSectionRTCPSender);
505
niklase@google.com470e71d2011-07-07 08:21:25 +0000506 if(_method == kRtcpOff)
507 {
508 return false;
509 }
510
niklase@google.com470e71d2011-07-07 08:21:25 +0000511 if(!_audio && sendKeyframeBeforeRTP)
512 {
513 // for video key-frames we want to send the RTCP before the large key-frame
514 // if we have a 100 ms margin
515 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
516 }
517
518 if(now > _nextTimeToSendRTCP)
519 {
520 return true;
521
522 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
523 {
524 // wrap
525 return true;
526 }
527 return false;
528}
529
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000530uint32_t
531RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000532{
533 CriticalSectionScoped lock(_criticalSectionRTCPSender);
534
535 lastRTCPTime = _lastRTCPTime[0];
536 return _lastSendReport[0];
537}
538
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000539uint32_t
540RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000541{
542 CriticalSectionScoped lock(_criticalSectionRTCPSender);
543
544 // This is only saved when we are the sender
545 if((_lastSendReport[0] == 0) || (sendReport == 0))
546 {
547 return 0; // will be ignored
548 } else
549 {
550 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
551 {
552 if( _lastSendReport[i] == sendReport)
553 {
554 return _lastRTCPTime[i];
555 }
556 }
557 }
558 return 0;
559}
560
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000561int32_t RTCPSender::AddReportBlock(const uint32_t SSRC,
562 const RTCPReportBlock* reportBlock) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000563 if (reportBlock == NULL) {
564 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
565 "%s invalid argument", __FUNCTION__);
566 return -1;
567 }
568 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000569
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000570 if (_reportBlocks.size() >= RTCP_MAX_REPORT_BLOCKS) {
571 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
572 "%s invalid argument", __FUNCTION__);
573 return -1;
574 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000575 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000576 _reportBlocks.find(SSRC);
577 if (it != _reportBlocks.end()) {
578 delete it->second;
579 _reportBlocks.erase(it);
580 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000581 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
582 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
583 _reportBlocks[SSRC] = copyReportBlock;
584 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000585}
586
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000587int32_t RTCPSender::RemoveReportBlock(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000588 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000589
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000590 std::map<uint32_t, RTCPReportBlock*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000591 _reportBlocks.find(SSRC);
592
593 if (it == _reportBlocks.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000594 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000595 }
596 delete it->second;
597 _reportBlocks.erase(it);
598 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000599}
600
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000601int32_t
602RTCPSender::BuildSR(uint8_t* rtcpbuffer,
603 uint32_t& pos,
604 const uint32_t NTPsec,
605 const uint32_t NTPfrac,
niklase@google.com470e71d2011-07-07 08:21:25 +0000606 const RTCPReportBlock* received)
607{
608 // sanity
609 if(pos + 52 >= IP_PACKET_SIZE)
610 {
611 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
612 return -2;
613 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000614 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000615
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000616 uint32_t posNumberOfReportBlocks = pos;
617 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000618
619 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000620 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000621
622 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
623 {
624 // shift old
625 _lastSendReport[i+1] = _lastSendReport[i];
626 _lastRTCPTime[i+1] =_lastRTCPTime[i];
627 }
628
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000629 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000630 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000631
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000632 uint32_t freqHz = 90000; // For video
633 if(_audio) {
634 freqHz = _rtpRtcp.CurrentSendFrequencyHz();
niklase@google.com470e71d2011-07-07 08:21:25 +0000635 }
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000636
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000637 // The timestamp of this RTCP packet should be estimated as the timestamp of
638 // the frame being captured at this moment. We are calculating that
639 // timestamp as the last frame's timestamp + the time since the last frame
640 // was captured.
641 {
642 // Needs protection since this method is called on the process thread.
643 CriticalSectionScoped lock(_criticalSectionRTCPSender);
644 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
645 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
646 (freqHz / 1000);
647 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000648
649 // Add sender data
650 // Save for our length field
651 pos++;
652 pos++;
653
654 // Add our own SSRC
655 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
656 pos += 4;
657 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000658 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000659 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000660 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000661 pos += 4;
662 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
663 pos += 4;
664
665 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000666 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000667 pos += 4;
668
669 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000670 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000671 pos += 4;
672
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000673 uint8_t numberOfReportBlocks = 0;
674 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000675 if(retVal < 0)
676 {
677 //
678 return retVal ;
679 }
680 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
681
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000682 uint16_t len = uint16_t((pos/4) -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000683 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
684 return 0;
685}
686
687
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000688int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer,
689 uint32_t& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000690 size_t lengthCname = strlen(_CNAME);
691 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000692
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000693 // sanity
694 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
695 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
696 "%s invalid argument", __FUNCTION__);
697 return -2;
698 }
699 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000700
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000701 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000702 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
703 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000704
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000705 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000706 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000707 pos++;
708 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000709
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000710 // Add our own SSRC
711 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
712 pos += 4;
713
714 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000715 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000716
717 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000718 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000719
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000720 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000721
722 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
723 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000724 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000725
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000726 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000727 // We must have a zero field even if we have an even multiple of 4 bytes
728 if ((pos % 4) == 0) {
729 padding++;
730 rtcpbuffer[pos++]=0;
731 }
732 while ((pos % 4) != 0) {
733 padding++;
734 rtcpbuffer[pos++]=0;
735 }
736 SDESLength += padding;
737
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000738 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000739 _csrcCNAMEs.begin();
740
741 for(; it != _csrcCNAMEs.end(); it++) {
742 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000743 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000744
745 // Add SSRC
746 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000747 pos += 4;
748
749 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000750 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000751
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000752 size_t length = strlen(cname->name);
753 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000754
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000755 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000756 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000757
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000758 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000759
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000760 pos += length;
761 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000762 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000763
764 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000765 if((pos % 4) == 0){
766 padding++;
767 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000768 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000769 while((pos % 4) != 0){
770 padding++;
771 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000772 }
773 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000774 }
775 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000776 uint16_t buffer_length = (SDESLength / 4) - 1;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000777 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
778 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000779 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000780}
781
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000782int32_t
783RTCPSender::BuildRR(uint8_t* rtcpbuffer,
784 uint32_t& pos,
785 const uint32_t NTPsec,
786 const uint32_t NTPfrac,
niklase@google.com470e71d2011-07-07 08:21:25 +0000787 const RTCPReportBlock* received)
788{
789 // sanity one block
790 if(pos + 32 >= IP_PACKET_SIZE)
791 {
792 return -2;
793 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000794 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000795
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000796 rtcpbuffer[pos++]=(uint8_t)0x80;
797 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000798
799 // Save for our length field
800 pos++;
801 pos++;
802
803 // Add our own SSRC
804 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
805 pos += 4;
806
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000807 uint8_t numberOfReportBlocks = 0;
808 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000809 if(retVal < 0)
810 {
811 return retVal;
812 }
813 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
814
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000815 uint16_t len = uint16_t((pos)/4 -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000816 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
817 return 0;
818}
819
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000820// From RFC 5450: Transmission Time Offsets in RTP Streams.
821// 0 1 2 3
822// 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
823// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
824// hdr |V=2|P| RC | PT=IJ=195 | length |
825// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
826// | inter-arrival jitter |
827// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
828// . .
829// . .
830// . .
831// | inter-arrival jitter |
832// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
833//
834// If present, this RTCP packet must be placed after a receiver report
835// (inside a compound RTCP packet), and MUST have the same value for RC
836// (reception report count) as the receiver report.
837
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000838int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000839RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000840 uint8_t* rtcpbuffer,
841 uint32_t& pos,
842 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000843{
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000844 if (_reportBlocks.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000845 {
846 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
847 return 0;
848 }
849
850 // sanity
851 if(pos + 8 >= IP_PACKET_SIZE)
852 {
853 return -2;
854 }
855 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000856 uint8_t RC = 1;
857 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
858 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000859
860 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000861 rtcpbuffer[pos++]=(uint8_t)0;
862 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000863
864 // Add inter-arrival jitter
865 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
866 jitterTransmissionTimeOffset);
867 pos += 4;
868 return 0;
869}
870
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000871int32_t
872RTCPSender::BuildPLI(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000873{
874 // sanity
875 if(pos + 12 >= IP_PACKET_SIZE)
876 {
877 return -2;
878 }
879 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000880 uint8_t FMT = 1;
881 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
882 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000883
884 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000885 rtcpbuffer[pos++]=(uint8_t)0;
886 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000887
888 // Add our own SSRC
889 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
890 pos += 4;
891
892 // Add the remote SSRC
893 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
894 pos += 4;
895 return 0;
896}
897
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000898int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
899 uint32_t& pos,
900 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000901 // sanity
902 if(pos + 20 >= IP_PACKET_SIZE) {
903 return -2;
904 }
905 if (!repeat) {
906 _sequenceNumberFIR++; // do not increase if repetition
907 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000908
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000909 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000910 uint8_t FMT = 4;
911 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
912 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000913
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000914 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000915 rtcpbuffer[pos++] = (uint8_t)0;
916 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000917
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000918 // Add our own SSRC
919 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
920 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000921
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000922 // RFC 5104 4.3.1.2. Semantics
923 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000924 rtcpbuffer[pos++] = (uint8_t)0;
925 rtcpbuffer[pos++] = (uint8_t)0;
926 rtcpbuffer[pos++] = (uint8_t)0;
927 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000928
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000929 // Additional Feedback Control Information (FCI)
930 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
931 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000932
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000933 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
934 rtcpbuffer[pos++] = (uint8_t)0;
935 rtcpbuffer[pos++] = (uint8_t)0;
936 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000937 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000938}
939
940/*
941 0 1 2 3
942 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
943 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
944 | First | Number | PictureID |
945 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
946*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000947int32_t
948RTCPSender::BuildSLI(uint8_t* rtcpbuffer, uint32_t& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000949{
950 // sanity
951 if(pos + 16 >= IP_PACKET_SIZE)
952 {
953 return -2;
954 }
955 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000956 uint8_t FMT = 2;
957 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
958 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000959
960 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000961 rtcpbuffer[pos++]=(uint8_t)0;
962 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000963
964 // Add our own SSRC
965 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
966 pos += 4;
967
968 // Add the remote SSRC
969 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
970 pos += 4;
971
972 // Add first, number & picture ID 6 bits
973 // first = 0, 13 - bits
974 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000975 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000976 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
977 pos += 4;
978 return 0;
979}
980
981/*
982 0 1 2 3
983 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
984 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
985 | PB |0| Payload Type| Native RPSI bit string |
986 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
987 | defined per codec ... | Padding (0) |
988 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
989*/
990/*
991* Note: not generic made for VP8
992*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000993int32_t
994RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
995 uint32_t& pos,
996 const uint64_t pictureID,
997 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +0000998{
999 // sanity
1000 if(pos + 24 >= IP_PACKET_SIZE)
1001 {
1002 return -2;
1003 }
1004 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001005 uint8_t FMT = 3;
1006 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1007 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001008
1009 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001010 uint32_t bitsRequired = 7;
1011 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001012 while((pictureID>>bitsRequired) > 0)
1013 {
1014 bitsRequired += 7;
1015 bytesRequired++;
1016 }
1017
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001018 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001019 if(bytesRequired > 6)
1020 {
1021 size = 5;
1022 } else if(bytesRequired > 2)
1023 {
1024 size = 4;
1025 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001026 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001027 rtcpbuffer[pos++]=size;
1028
1029 // Add our own SSRC
1030 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1031 pos += 4;
1032
1033 // Add the remote SSRC
1034 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1035 pos += 4;
1036
1037 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001038 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001039 if(paddingBytes == 4)
1040 {
1041 paddingBytes = 0;
1042 }
1043 // add padding length in bits
1044 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1045 pos++;
1046
1047 // add payload type
1048 rtcpbuffer[pos] = payloadType;
1049 pos++;
1050
1051 // add picture ID
1052 for(int i = bytesRequired-1; i > 0; i--)
1053 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001054 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001055 pos++;
1056 }
1057 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001058 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001059 pos++;
1060
1061 // add padding
1062 for(int j = 0; j <paddingBytes; j++)
1063 {
1064 rtcpbuffer[pos] = 0;
1065 pos++;
1066 }
1067 return 0;
1068}
1069
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001070int32_t
1071RTCPSender::BuildREMB(uint8_t* rtcpbuffer, uint32_t& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001072{
1073 // sanity
1074 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1075 {
1076 return -2;
1077 }
1078 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001079 uint8_t FMT = 15;
1080 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1081 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001082
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001083 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001084 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1085
1086 // Add our own SSRC
1087 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1088 pos += 4;
1089
1090 // Remote SSRC must be 0
1091 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1092 pos += 4;
1093
1094 rtcpbuffer[pos++]='R';
1095 rtcpbuffer[pos++]='E';
1096 rtcpbuffer[pos++]='M';
1097 rtcpbuffer[pos++]='B';
1098
1099 rtcpbuffer[pos++] = _lengthRembSSRC;
1100 // 6 bit Exp
1101 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001102 uint8_t brExp = 0;
1103 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001104 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001105 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001106 {
1107 brExp = i;
1108 break;
1109 }
1110 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001111 const uint32_t brMantissa = (_rembBitrate >> brExp);
1112 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1113 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1114 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001115
1116 for (int i = 0; i < _lengthRembSSRC; i++)
1117 {
1118 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1119 pos += 4;
1120 }
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001121 TRACE_COUNTER_ID1("webrtc_rtp", "RTCPRembBitrate", _SSRC, _rembBitrate);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001122 return 0;
1123}
1124
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001125void
1126RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001127{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001128 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001129 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001130}
1131
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001132int32_t
1133RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001134{
1135 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1136 // If the sender is an owner of the TMMBN -> send TMMBR
1137 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1138
niklase@google.com470e71d2011-07-07 08:21:25 +00001139 // get current bounding set from RTCP receiver
1140 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001141 // store in candidateSet, allocates one extra slot
1142 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001143
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001144 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1145 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1146 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001147 int32_t lengthOfBoundingSet
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001148 = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001149
1150 if(lengthOfBoundingSet > 0)
1151 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001152 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001153 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001154 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1155 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001156 {
1157 // do not send the same tuple
1158 return 0;
1159 }
1160 }
1161 if(!tmmbrOwner)
1162 {
1163 // use received bounding set as candidate set
1164 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001165 candidateSet->SetEntry(lengthOfBoundingSet,
1166 _tmmbr_Send,
1167 _packetOH_Send,
1168 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001169 int numCandidates = lengthOfBoundingSet+ 1;
1170
1171 // find bounding set
1172 TMMBRSet* boundingSet = NULL;
1173 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1174 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1175 {
1176 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1177 }
1178 if(!tmmbrOwner)
1179 {
1180 // did not enter bounding set, no meaning to send this request
1181 return 0;
1182 }
1183 }
1184 }
1185
1186 if(_tmmbr_Send)
1187 {
1188 // sanity
1189 if(pos + 20 >= IP_PACKET_SIZE)
1190 {
1191 return -2;
1192 }
1193 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001194 uint8_t FMT = 3;
1195 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1196 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001197
1198 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001199 rtcpbuffer[pos++]=(uint8_t)0;
1200 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001201
1202 // Add our own SSRC
1203 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1204 pos += 4;
1205
1206 // RFC 5104 4.2.1.2. Semantics
1207
1208 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001209 rtcpbuffer[pos++]=(uint8_t)0;
1210 rtcpbuffer[pos++]=(uint8_t)0;
1211 rtcpbuffer[pos++]=(uint8_t)0;
1212 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001213
1214 // Additional Feedback Control Information (FCI)
1215 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1216 pos += 4;
1217
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001218 uint32_t bitRate = _tmmbr_Send*1000;
1219 uint32_t mmbrExp = 0;
1220 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001221 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001222 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001223 {
1224 mmbrExp = i;
1225 break;
1226 }
1227 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001228 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001229
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001230 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1231 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1232 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1233 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001234 }
1235 return 0;
1236}
1237
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001238int32_t
1239RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001240{
1241 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1242 if(boundingSet == NULL)
1243 {
1244 return -1;
1245 }
1246 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001247 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001248 {
1249 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1250 return -2;
1251 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001252 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001253 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001254 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1255 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001256
1257 //Add length later
1258 int posLength = pos;
1259 pos++;
1260 pos++;
1261
1262 // Add our own SSRC
1263 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1264 pos += 4;
1265
1266 // RFC 5104 4.2.2.2. Semantics
1267
1268 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001269 rtcpbuffer[pos++]=(uint8_t)0;
1270 rtcpbuffer[pos++]=(uint8_t)0;
1271 rtcpbuffer[pos++]=(uint8_t)0;
1272 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001273
1274 // Additional Feedback Control Information (FCI)
1275 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001276 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001277 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001278 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001279 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001280 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001281 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1282 pos += 4;
1283
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001284 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1285 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001286 for(int i=0; i<64; i++)
1287 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001288 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001289 {
1290 mmbrExp = i;
1291 break;
1292 }
1293 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001294 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1295 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001296
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001297 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1298 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1299 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1300 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001301 numBoundingSet++;
1302 }
1303 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001304 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1305 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1306 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001307 return 0;
1308}
1309
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001310int32_t
1311RTCPSender::BuildAPP(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001312{
1313 // sanity
1314 if(_appData == NULL)
1315 {
1316 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1317 return -1;
1318 }
1319 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1320 {
1321 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1322 return -2;
1323 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001324 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001325
1326 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001327 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001328
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001329 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1330 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1331 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001332
1333 // Add our own SSRC
1334 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1335 pos += 4;
1336
1337 // Add our application name
1338 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1339 pos += 4;
1340
1341 // Add the data
1342 memcpy(rtcpbuffer +pos, _appData,_appLength);
1343 pos += _appLength;
1344 return 0;
1345}
1346
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001347int32_t
1348RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
1349 uint32_t& pos,
1350 const int32_t nackSize,
1351 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001352 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001353{
1354 // sanity
1355 if(pos + 16 >= IP_PACKET_SIZE)
1356 {
1357 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1358 return -2;
1359 }
1360
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001361 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001362 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001363 uint8_t FMT = 1;
1364 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1365 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001366
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001367 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001368 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001369 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001370
1371 // Add our own SSRC
1372 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1373 pos += 4;
1374
1375 // Add the remote SSRC
1376 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1377 pos += 4;
1378
edjee@google.com79b02892013-04-04 19:43:34 +00001379 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001380 // Build NACK bitmasks and write them to the RTCP message.
1381 // The nack list should be sorted and not contain duplicates if one
1382 // wants to build the smallest rtcp nack packet.
1383 int numOfNackFields = 0;
1384 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1385 (IP_PACKET_SIZE - pos) / 4);
1386 int i = 0;
1387 while (i < nackSize && numOfNackFields < maxNackFields) {
1388 stringBuilder.PushNACK(nackList[i]);
1389 uint16_t nack = nackList[i++];
1390 uint16_t bitmask = 0;
1391 while (i < nackSize) {
1392 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1393 if (shift >= 0 && shift <= 15) {
1394 stringBuilder.PushNACK(nackList[i]);
1395 bitmask |= (1 << shift);
1396 ++i;
1397 } else {
1398 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001399 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001400 }
1401 // Write the sequence number and the bitmask to the packet.
1402 assert(pos + 4 < IP_PACKET_SIZE);
1403 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
1404 pos += 2;
1405 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
1406 pos += 2;
1407 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001408 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001409 if (i != nackSize) {
1410 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1411 "Nack list to large for one packet.");
1412 }
1413 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001414 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001415 return 0;
1416}
1417
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001418int32_t
1419RTCPSender::BuildBYE(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001420{
1421 // sanity
1422 if(pos + 8 >= IP_PACKET_SIZE)
1423 {
1424 return -2;
1425 }
1426 if(_includeCSRCs)
1427 {
1428 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001429 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1430 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001431
1432 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001433 rtcpbuffer[pos++]=(uint8_t)0;
1434 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001435
1436 // Add our own SSRC
1437 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1438 pos += 4;
1439
1440 // add CSRCs
1441 for(int i = 0; i < _CSRCs; i++)
1442 {
1443 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1444 pos += 4;
1445 }
1446 } else
1447 {
1448 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001449 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1450 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001451
1452 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001453 rtcpbuffer[pos++]=(uint8_t)0;
1454 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001455
1456 // Add our own SSRC
1457 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1458 pos += 4;
1459 }
1460 return 0;
1461}
1462
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001463int32_t
1464RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001465{
1466 // sanity
1467 if(pos + 44 >= IP_PACKET_SIZE)
1468 {
1469 return -2;
1470 }
1471
1472 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001473 rtcpbuffer[pos++]=(uint8_t)0x80;
1474 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001475
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001476 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001477
1478 // handle length later on
1479 pos++;
1480 pos++;
1481
1482 // Add our own SSRC
1483 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1484 pos += 4;
1485
1486 // Add a VoIP metrics block
1487 rtcpbuffer[pos++]=7;
1488 rtcpbuffer[pos++]=0;
1489 rtcpbuffer[pos++]=0;
1490 rtcpbuffer[pos++]=8;
1491
1492 // Add the remote SSRC
1493 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1494 pos += 4;
1495
1496 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1497 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1498 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1499 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1500
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001501 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1502 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1503 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1504 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001505
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001506 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1507 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1508 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1509 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001510
1511 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1512 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1513 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1514 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1515
1516 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1517 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1518 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1519 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1520
1521 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1522 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001523 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1524 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001525
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001526 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1527 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1528 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1529 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001530
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001531 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1532 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001533 return 0;
1534}
1535
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001536int32_t
1537RTCPSender::SendRTCP(const uint32_t packetTypeFlags,
1538 const int32_t nackSize, // NACK
1539 const uint16_t* nackList, // NACK
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001540 const bool repeat, // FIR
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001541 const uint64_t pictureID) // SLI & RPSI
niklase@google.com470e71d2011-07-07 08:21:25 +00001542{
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001543 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1544 uint32_t pos = 0;
1545 uint8_t rtcpbuffer[IP_PACKET_SIZE];
niklase@google.com470e71d2011-07-07 08:21:25 +00001546
niklase@google.com470e71d2011-07-07 08:21:25 +00001547 do // only to be able to use break :) (and the critsect must be inside its own scope)
1548 {
1549 // collect the received information
1550 RTCPReportBlock received;
1551 bool hasReceived = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001552 uint32_t NTPsec = 0;
1553 uint32_t NTPfrac = 0;
xians@webrtc.org8738d272011-11-25 13:43:53 +00001554 bool rtcpCompound = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001555 uint32_t jitterTransmissionOffset = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001556
xians@webrtc.org8738d272011-11-25 13:43:53 +00001557 {
1558 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1559 if(_method == kRtcpOff)
1560 {
1561 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1562 "%s invalid state", __FUNCTION__);
1563 return -1;
1564 }
1565 rtcpCompound = (_method == kRtcpCompound) ? true : false;
1566 }
1567
1568 if (rtcpCompound ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001569 rtcpPacketTypeFlags & kRtcpReport ||
1570 rtcpPacketTypeFlags & kRtcpSr ||
1571 rtcpPacketTypeFlags & kRtcpRr)
1572 {
1573 // get statistics from our RTPreceiver outside critsect
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001574 if(_rtpRtcp.ReportBlockStatistics(&received.fractionLost,
1575 &received.cumulativeLost,
1576 &received.extendedHighSeqNum,
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001577 &received.jitter,
1578 &jitterTransmissionOffset) == 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001579 {
1580 hasReceived = true;
1581
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001582 uint32_t lastReceivedRRNTPsecs = 0;
1583 uint32_t lastReceivedRRNTPfrac = 0;
1584 uint32_t remoteSR = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001585
1586 // ok even if we have not received a SR, we will send 0 in that case
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001587 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1588 lastReceivedRRNTPfrac,
1589 remoteSR);
niklase@google.com470e71d2011-07-07 08:21:25 +00001590
1591 // get our NTP as late as possible to avoid a race
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001592 _clock->CurrentNtp(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001593
1594 // Delay since last received report
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001595 uint32_t delaySinceLastReceivedSR = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001596 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
1597 {
1598 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001599 uint32_t now=NTPsec&0x0000FFFF;
niklase@google.com470e71d2011-07-07 08:21:25 +00001600 now <<=16;
1601 now += (NTPfrac&0xffff0000)>>16;
1602
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001603 uint32_t receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
niklase@google.com470e71d2011-07-07 08:21:25 +00001604 receiveTime <<=16;
1605 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1606
1607 delaySinceLastReceivedSR = now-receiveTime;
1608 }
1609 received.delaySinceLastSR = delaySinceLastReceivedSR;
1610 received.lastSR = remoteSR;
1611 } else
1612 {
1613 // we need to send our NTP even if we dont have received any reports
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001614 _clock->CurrentNtp(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001615 }
1616 }
1617
1618 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1619
1620 if(_TMMBR ) // attach TMMBR to send and receive reports
1621 {
1622 rtcpPacketTypeFlags |= kRtcpTmmbr;
1623 }
1624 if(_appSend)
1625 {
1626 rtcpPacketTypeFlags |= kRtcpApp;
1627 _appSend = false;
1628 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001629 if(_REMB && _sendREMB)
1630 {
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +00001631 // Always attach REMB to SR if that is configured. Note that REMB is
1632 // only sent on one of the RTP modules in the REMB group.
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001633 rtcpPacketTypeFlags |= kRtcpRemb;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001634 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001635 if(_xrSendVoIPMetric)
1636 {
1637 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1638 _xrSendVoIPMetric = false;
1639 }
1640 if(_sendTMMBN) // set when having received a TMMBR
1641 {
1642 rtcpPacketTypeFlags |= kRtcpTmmbn;
1643 _sendTMMBN = false;
1644 }
1645
1646 if(_method == kRtcpCompound)
1647 {
1648 if(_sending)
1649 {
1650 rtcpPacketTypeFlags |= kRtcpSr;
1651 } else
1652 {
1653 rtcpPacketTypeFlags |= kRtcpRr;
1654 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001655 if (_IJ && hasReceived)
1656 {
1657 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1658 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001659 } else if(_method == kRtcpNonCompound)
1660 {
1661 if(rtcpPacketTypeFlags & kRtcpReport)
1662 {
1663 if(_sending)
1664 {
1665 rtcpPacketTypeFlags |= kRtcpSr;
1666 } else
1667 {
1668 rtcpPacketTypeFlags |= kRtcpRr;
1669 }
1670 }
1671 }
1672 if( rtcpPacketTypeFlags & kRtcpRr ||
1673 rtcpPacketTypeFlags & kRtcpSr)
1674 {
1675 // generate next time to send a RTCP report
1676 // seeded from RTP constructor
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001677 int32_t random = rand() % 1000;
1678 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
niklase@google.com470e71d2011-07-07 08:21:25 +00001679
1680 if(_audio)
1681 {
1682 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
1683 }else
1684 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001685 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
niklase@google.com470e71d2011-07-07 08:21:25 +00001686 if(_sending)
1687 {
1688 // calc bw for video 360/sendBW in kbit/s
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001689 uint32_t sendBitrateKbit = 0;
1690 uint32_t videoRate = 0;
1691 uint32_t fecRate = 0;
1692 uint32_t nackRate = 0;
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001693 _rtpRtcp.BitrateSent(&sendBitrateKbit,
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001694 &videoRate,
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001695 &fecRate,
1696 &nackRate);
1697 sendBitrateKbit /= 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001698 if(sendBitrateKbit != 0)
1699 {
1700 minIntervalMs = 360000/sendBitrateKbit;
1701 }
1702 }
1703 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1704 {
1705 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1706 }
1707 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1708 }
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001709 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
niklase@google.com470e71d2011-07-07 08:21:25 +00001710 }
1711
1712 // if the data does not fitt in the packet we fill it as much as possible
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001713 int32_t buildVal = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001714
1715 if(rtcpPacketTypeFlags & kRtcpSr)
1716 {
1717 if(hasReceived)
1718 {
1719 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
1720 } else
1721 {
1722 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac);
1723 }
1724 if(buildVal == -1)
1725 {
1726 return -1; // error
1727
1728 }else if(buildVal == -2)
1729 {
1730 break; // out of buffer
1731 }
1732 buildVal = BuildSDEC(rtcpbuffer, pos);
1733 if(buildVal == -1)
1734 {
1735 return -1; // error
1736
1737 }else if(buildVal == -2)
1738 {
1739 break; // out of buffer
1740 }
1741
1742 }else if(rtcpPacketTypeFlags & kRtcpRr)
1743 {
1744 if(hasReceived)
1745 {
1746 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
1747 }else
1748 {
1749 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
1750 }
1751 if(buildVal == -1)
1752 {
1753 return -1; // error
1754
1755 }else if(buildVal == -2)
1756 {
1757 break; // out of buffer
1758 }
1759 // only of set
1760 if(_CNAME[0] != 0)
1761 {
1762 buildVal = BuildSDEC(rtcpbuffer, pos);
1763 if(buildVal == -1)
1764 {
1765 return -1; // error
1766 }
1767 }
1768 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001769 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1770 {
1771 // If present, this RTCP packet must be placed after a
1772 // receiver report.
1773 buildVal = BuildExtendedJitterReport(rtcpbuffer,
1774 pos,
1775 jitterTransmissionOffset);
1776 if(buildVal == -1)
1777 {
1778 return -1; // error
1779 }
1780 else if(buildVal == -2)
1781 {
1782 break; // out of buffer
1783 }
1784 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001785 if(rtcpPacketTypeFlags & kRtcpPli)
1786 {
1787 buildVal = BuildPLI(rtcpbuffer, pos);
1788 if(buildVal == -1)
1789 {
1790 return -1; // error
1791
1792 }else if(buildVal == -2)
1793 {
1794 break; // out of buffer
1795 }
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001796 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
edjee@google.com79b02892013-04-04 19:43:34 +00001797 _pliCount++;
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001798 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC, _pliCount);
niklase@google.com470e71d2011-07-07 08:21:25 +00001799 }
1800 if(rtcpPacketTypeFlags & kRtcpFir)
1801 {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001802 buildVal = BuildFIR(rtcpbuffer, pos, repeat);
niklase@google.com470e71d2011-07-07 08:21:25 +00001803 if(buildVal == -1)
1804 {
1805 return -1; // error
1806
1807 }else if(buildVal == -2)
1808 {
1809 break; // out of buffer
1810 }
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001811 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
edjee@google.com79b02892013-04-04 19:43:34 +00001812 _fullIntraRequestCount++;
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001813 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
1814 _fullIntraRequestCount);
niklase@google.com470e71d2011-07-07 08:21:25 +00001815 }
1816 if(rtcpPacketTypeFlags & kRtcpSli)
1817 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001818 buildVal = BuildSLI(rtcpbuffer, pos, (uint8_t)pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +00001819 if(buildVal == -1)
1820 {
1821 return -1; // error
1822
1823 }else if(buildVal == -2)
1824 {
1825 break; // out of buffer
1826 }
1827 }
1828 if(rtcpPacketTypeFlags & kRtcpRpsi)
1829 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001830 const int8_t payloadType = _rtpRtcp.SendPayloadType();
niklase@google.com470e71d2011-07-07 08:21:25 +00001831 if(payloadType == -1)
1832 {
1833 return -1;
1834 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001835 buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (uint8_t)payloadType);
niklase@google.com470e71d2011-07-07 08:21:25 +00001836 if(buildVal == -1)
1837 {
1838 return -1; // error
1839
1840 }else if(buildVal == -2)
1841 {
1842 break; // out of buffer
1843 }
1844 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001845 if(rtcpPacketTypeFlags & kRtcpRemb)
1846 {
1847 buildVal = BuildREMB(rtcpbuffer, pos);
1848 if(buildVal == -1)
1849 {
1850 return -1; // error
1851
1852 }else if(buildVal == -2)
1853 {
1854 break; // out of buffer
1855 }
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001856 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001857 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001858 if(rtcpPacketTypeFlags & kRtcpBye)
1859 {
1860 buildVal = BuildBYE(rtcpbuffer, pos);
1861 if(buildVal == -1)
1862 {
1863 return -1; // error
1864
1865 }else if(buildVal == -2)
1866 {
1867 break; // out of buffer
1868 }
1869 }
1870 if(rtcpPacketTypeFlags & kRtcpApp)
1871 {
1872 buildVal = BuildAPP(rtcpbuffer, pos);
1873 if(buildVal == -1)
1874 {
1875 return -1; // error
1876
1877 }else if(buildVal == -2)
1878 {
1879 break; // out of buffer
1880 }
1881 }
1882 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1883 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001884 buildVal = BuildTMMBR(rtcpbuffer, pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001885 if(buildVal == -1)
1886 {
1887 return -1; // error
1888
1889 }else if(buildVal == -2)
1890 {
1891 break; // out of buffer
1892 }
1893 }
1894 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1895 {
1896 buildVal = BuildTMMBN(rtcpbuffer, pos);
1897 if(buildVal == -1)
1898 {
1899 return -1; // error
1900
1901 }else if(buildVal == -2)
1902 {
1903 break; // out of buffer
1904 }
1905 }
1906 if(rtcpPacketTypeFlags & kRtcpNack)
1907 {
edjee@google.com79b02892013-04-04 19:43:34 +00001908 std::string nackString;
1909 buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList,
1910 &nackString);
niklase@google.com470e71d2011-07-07 08:21:25 +00001911 if(buildVal == -1)
1912 {
1913 return -1; // error
1914
1915 }else if(buildVal == -2)
1916 {
1917 break; // out of buffer
1918 }
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001919 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
1920 "nacks", TRACE_STR_COPY(nackString.c_str()));
edjee@google.com79b02892013-04-04 19:43:34 +00001921 _nackCount++;
hclam@chromium.org806dc3b2013-04-09 19:54:10 +00001922 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC, _nackCount);
niklase@google.com470e71d2011-07-07 08:21:25 +00001923 }
1924 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1925 {
1926 buildVal = BuildVoIPMetric(rtcpbuffer, pos);
1927 if(buildVal == -1)
1928 {
1929 return -1; // error
1930
1931 }else if(buildVal == -2)
1932 {
1933 break; // out of buffer
1934 }
1935 }
1936 }while (false);
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001937 // Sanity don't send empty packets.
1938 if (pos == 0)
1939 {
1940 return -1;
1941 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001942 return SendToNetwork(rtcpbuffer, (uint16_t)pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001943}
1944
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001945int32_t
1946RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
1947 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001948{
1949 CriticalSectionScoped lock(_criticalSectionTransport);
1950 if(_cbTransport)
1951 {
1952 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1953 {
1954 return 0;
1955 }
1956 }
1957 return -1;
1958}
1959
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001960int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00001961RTCPSender::SetCSRCStatus(const bool include)
1962{
1963 _includeCSRCs = include;
1964 return 0;
1965}
1966
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001967int32_t
1968RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
1969 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00001970{
1971 if(arrLength > kRtpCsrcSize)
1972 {
1973 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1974 assert(false);
1975 return -1;
1976 }
1977
1978 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1979
1980 for(int i = 0; i < arrLength;i++)
1981 {
1982 _CSRC[i] = arrOfCSRC[i];
1983 }
1984 _CSRCs = arrLength;
1985 return 0;
1986}
1987
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001988int32_t
1989RTCPSender::SetApplicationSpecificData(const uint8_t subType,
1990 const uint32_t name,
1991 const uint8_t* data,
1992 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001993{
1994 if(length %4 != 0)
1995 {
1996 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1997 return -1;
1998 }
1999 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2000
2001 if(_appData)
2002 {
2003 delete [] _appData;
2004 }
2005
2006 _appSend = true;
2007 _appSubType = subType;
2008 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002009 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002010 _appLength = length;
2011 memcpy(_appData, data, length);
2012 return 0;
2013}
2014
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002015int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002016RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2017{
2018 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2019 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2020
2021 _xrSendVoIPMetric = true;
2022 return 0;
2023}
2024
2025// called under critsect _criticalSectionRTCPSender
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002026int32_t RTCPSender::AddReportBlocks(uint8_t* rtcpbuffer,
2027 uint32_t& pos,
2028 uint8_t& numberOfReportBlocks,
2029 const RTCPReportBlock* received,
2030 const uint32_t NTPsec,
2031 const uint32_t NTPfrac) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002032 // sanity one block
2033 if(pos + 24 >= IP_PACKET_SIZE) {
2034 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2035 "%s invalid argument", __FUNCTION__);
2036 return -1;
2037 }
2038 numberOfReportBlocks = _reportBlocks.size();
2039 if (received) {
2040 // add our multiple RR to numberOfReportBlocks
2041 numberOfReportBlocks++;
2042 }
2043 if (received) {
2044 // answer to the one that sends to me
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +00002045 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002046
2047 // Remote SSRC
2048 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
2049 pos += 4;
2050
2051 // fraction lost
2052 rtcpbuffer[pos++]=received->fractionLost;
2053
2054 // cumulative loss
2055 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2056 received->cumulativeLost);
2057 pos += 3;
2058 // extended highest seq_no, contain the highest sequence number received
2059 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2060 received->extendedHighSeqNum);
2061 pos += 4;
2062
2063 //Jitter
2064 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
2065 pos += 4;
2066
2067 // Last SR timestamp, our NTP time when we received the last report
2068 // This is the value that we read from the send report packet not when we
2069 // received it...
2070 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
2071 pos += 4;
2072
2073 // Delay since last received report,time since we received the report
2074 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2075 received->delaySinceLastSR);
2076 pos += 4;
2077 }
2078 if ((pos + _reportBlocks.size() * 24) >= IP_PACKET_SIZE) {
2079 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2080 "%s invalid argument", __FUNCTION__);
2081 return -1;
2082 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002083 std::map<uint32_t, RTCPReportBlock*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002084 _reportBlocks.begin();
2085
2086 for (; it != _reportBlocks.end(); it++) {
2087 // we can have multiple report block in a conference
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002088 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002089 RTCPReportBlock* reportBlock = it->second;
2090 if (reportBlock) {
2091 // Remote SSRC
2092 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
2093 pos += 4;
2094
2095 // fraction lost
2096 rtcpbuffer[pos++] = reportBlock->fractionLost;
2097
2098 // cumulative loss
2099 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2100 reportBlock->cumulativeLost);
2101 pos += 3;
2102
2103 // extended highest seq_no, contain the highest sequence number received
2104 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2105 reportBlock->extendedHighSeqNum);
2106 pos += 4;
2107
2108 //Jitter
2109 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2110 reportBlock->jitter);
2111 pos += 4;
2112
2113 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2114 reportBlock->lastSR);
2115 pos += 4;
2116
2117 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2118 reportBlock->delaySinceLastSR);
2119 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002120 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002121 }
2122 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00002123}
2124
2125// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002126int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002127RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002128 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002129{
2130 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2131
2132 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2133 {
2134 _sendTMMBN = true;
2135 return 0;
2136 }
2137 return -1;
2138}
niklase@google.com470e71d2011-07-07 08:21:25 +00002139} // namespace webrtc