blob: c333186bc9d956e1a6130f2a2b9269e5c89e08c4 [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
niklase@google.com470e71d2011-07-07 08:21:25 +000094 _lastSendReport(),
95 _lastRTCPTime(),
96
97 _CSRCs(0),
98 _CSRC(),
99 _includeCSRCs(true),
100
101 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000102
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000103 _lengthRembSSRC(0),
104 _sizeRembSSRC(0),
105 _rembSSRC(NULL),
106 _rembBitrate(0),
107
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000108 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000109 _tmmbr_Send(0),
110 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000111
112 _appSend(false),
113 _appSubType(0),
114 _appName(),
115 _appData(NULL),
116 _appLength(0),
117 _xrSendVoIPMetric(false),
edjee@google.com79b02892013-04-04 19:43:34 +0000118 _xrVoIPMetric(),
119 _nackCount(0),
120 _pliCount(0),
121 _fullIntraRequestCount(0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000122{
123 memset(_CNAME, 0, sizeof(_CNAME));
124 memset(_lastSendReport, 0, sizeof(_lastSendReport));
125 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
126
127 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
128}
129
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000130RTCPSender::~RTCPSender() {
131 delete [] _rembSSRC;
132 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000133
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000134 while (!_reportBlocks.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000135 std::map<uint32_t, RTCPReportBlock*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000136 _reportBlocks.begin();
137 delete it->second;
138 _reportBlocks.erase(it);
139 }
140 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000141 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000142 _csrcCNAMEs.begin();
143 delete it->second;
144 _csrcCNAMEs.erase(it);
145 }
146 delete _criticalSectionTransport;
147 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000148
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000149 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000150}
151
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000152int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000153RTCPSender::Init()
154{
155 CriticalSectionScoped lock(_criticalSectionRTCPSender);
156
157 _method = kRtcpOff;
158 _cbTransport = NULL;
159 _usingNack = false;
160 _sending = false;
161 _sendTMMBN = false;
162 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000163 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000164 _REMB = false;
165 _sendREMB = false;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000166 last_rtp_timestamp_ = 0;
167 last_frame_capture_time_ms_ = -1;
168 start_timestamp_ = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000169 _SSRC = 0;
170 _remoteSSRC = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000171 _sequenceNumberFIR = 0;
172 _tmmbr_Send = 0;
173 _packetOH_Send = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000174 _nextTimeToSendRTCP = 0;
175 _CSRCs = 0;
176 _appSend = false;
177 _appSubType = 0;
178
179 if(_appData)
180 {
181 delete [] _appData;
182 _appData = NULL;
183 }
184 _appLength = 0;
185
186 _xrSendVoIPMetric = false;
187
188 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
189 memset(_CNAME, 0, sizeof(_CNAME));
190 memset(_lastSendReport, 0, sizeof(_lastSendReport));
191 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
edjee@google.com79b02892013-04-04 19:43:34 +0000192
193 _nackCount = 0;
194 _pliCount = 0;
195 _fullIntraRequestCount = 0;
196
niklase@google.com470e71d2011-07-07 08:21:25 +0000197 return 0;
198}
199
200void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000201RTCPSender::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +0000202{
203 _id = id;
204}
205
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000206int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000207RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
208{
209 CriticalSectionScoped lock(_criticalSectionTransport);
210 _cbTransport = outgoingTransport;
211 return 0;
212}
213
214RTCPMethod
215RTCPSender::Status() const
216{
217 CriticalSectionScoped lock(_criticalSectionRTCPSender);
218 return _method;
219}
220
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000221int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000222RTCPSender::SetRTCPStatus(const RTCPMethod method)
223{
224 CriticalSectionScoped lock(_criticalSectionRTCPSender);
225 if(method != kRtcpOff)
226 {
227 if(_audio)
228 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000229 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000230 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 } else
232 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000233 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000234 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000235 }
236 }
237 _method = method;
238 return 0;
239}
240
241bool
242RTCPSender::Sending() const
243{
244 CriticalSectionScoped lock(_criticalSectionRTCPSender);
245 return _sending;
246}
247
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000248int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000249RTCPSender::SetSendingStatus(const bool sending)
250{
251 bool sendRTCPBye = false;
252 {
253 CriticalSectionScoped lock(_criticalSectionRTCPSender);
254
255 if(_method != kRtcpOff)
256 {
257 if(sending == false && _sending == true)
258 {
259 // Trigger RTCP bye
260 sendRTCPBye = true;
261 }
262 }
263 _sending = sending;
264 }
265 if(sendRTCPBye)
266 {
267 return SendRTCP(kRtcpBye);
268 }
269 return 0;
270}
271
272bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000273RTCPSender::REMB() const
274{
275 CriticalSectionScoped lock(_criticalSectionRTCPSender);
276 return _REMB;
277}
278
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000279int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000280RTCPSender::SetREMBStatus(const bool enable)
281{
282 CriticalSectionScoped lock(_criticalSectionRTCPSender);
283 _REMB = enable;
284 return 0;
285}
286
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000287int32_t
288RTCPSender::SetREMBData(const uint32_t bitrate,
289 const uint8_t numberOfSSRC,
290 const uint32_t* SSRC)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000291{
292 CriticalSectionScoped lock(_criticalSectionRTCPSender);
293 _rembBitrate = bitrate;
294
295 if(_sizeRembSSRC < numberOfSSRC)
296 {
297 delete [] _rembSSRC;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000298 _rembSSRC = new uint32_t[numberOfSSRC];
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000299 _sizeRembSSRC = numberOfSSRC;
300 }
301
302 _lengthRembSSRC = numberOfSSRC;
303 for (int i = 0; i < numberOfSSRC; i++)
304 {
305 _rembSSRC[i] = SSRC[i];
306 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000307 _sendREMB = true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000308 return 0;
309}
310
311bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000312RTCPSender::TMMBR() const
313{
314 CriticalSectionScoped lock(_criticalSectionRTCPSender);
315 return _TMMBR;
316}
317
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000318int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000319RTCPSender::SetTMMBRStatus(const bool enable)
320{
321 CriticalSectionScoped lock(_criticalSectionRTCPSender);
322 _TMMBR = enable;
323 return 0;
324}
325
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000326bool
327RTCPSender::IJ() const
328{
329 CriticalSectionScoped lock(_criticalSectionRTCPSender);
330 return _IJ;
331}
332
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000333int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000334RTCPSender::SetIJStatus(const bool enable)
335{
336 CriticalSectionScoped lock(_criticalSectionRTCPSender);
337 _IJ = enable;
338 return 0;
339}
340
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000341void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
342 start_timestamp_ = start_timestamp;
343}
344
345void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
346 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000347 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000348 last_rtp_timestamp_ = rtp_timestamp;
349 if (capture_time_ms < 0) {
350 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.orgafcc6102013-04-09 13:37:40 +0000351 last_frame_capture_time_ms_ = _clock->CurrentNtpInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000352 } else {
353 last_frame_capture_time_ms_ = capture_time_ms;
354 }
355}
356
niklase@google.com470e71d2011-07-07 08:21:25 +0000357void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000358RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000359{
360 CriticalSectionScoped lock(_criticalSectionRTCPSender);
361
362 if(_SSRC != 0)
363 {
364 // not first SetSSRC, probably due to a collision
365 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000366 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000367 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000368 }
369 _SSRC = ssrc;
370}
371
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000372int32_t
373RTCPSender::SetRemoteSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000374{
375 CriticalSectionScoped lock(_criticalSectionRTCPSender);
376 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000377 return 0;
378}
379
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000380int32_t RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000381 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000382 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000383 cName[RTCP_CNAME_SIZE - 1] = 0;
384 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000385 return 0;
386}
387
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000388int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000389 if (!cName)
390 return -1;
391
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000392 CriticalSectionScoped lock(_criticalSectionRTCPSender);
393 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
394 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
395 return 0;
396}
397
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000398int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
399 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000400 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000401 CriticalSectionScoped lock(_criticalSectionRTCPSender);
402 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
403 return -1;
404 }
405 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000406 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
407 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000408 _csrcCNAMEs[SSRC] = ptr;
409 return 0;
410}
411
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000412int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000413 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000414 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000415 _csrcCNAMEs.find(SSRC);
416
417 if (it == _csrcCNAMEs.end()) {
418 return -1;
419 }
420 delete it->second;
421 _csrcCNAMEs.erase(it);
422 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000423}
424
425bool
426RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
427{
428/*
429 For audio we use a fix 5 sec interval
430
431 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
432 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
433
434
435From RFC 3550
436
437 MAX RTCP BW is 5% if the session BW
438 A send report is approximately 65 bytes inc CNAME
439 A report report is approximately 28 bytes
440
441 The RECOMMENDED value for the reduced minimum in seconds is 360
442 divided by the session bandwidth in kilobits/second. This minimum
443 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
444
445 If the participant has not yet sent an RTCP packet (the variable
446 initial is true), the constant Tmin is set to 2.5 seconds, else it
447 is set to 5 seconds.
448
449 The interval between RTCP packets is varied randomly over the
450 range [0.5,1.5] times the calculated interval to avoid unintended
451 synchronization of all participants
452
453 if we send
454 If the participant is a sender (we_sent true), the constant C is
455 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
456 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
457 number of senders.
458
459 if we receive only
460 If we_sent is not true, the constant C is set
461 to the average RTCP packet size divided by 75% of the RTCP
462 bandwidth. The constant n is set to the number of receivers
463 (members - senders). If the number of senders is greater than
464 25%, senders and receivers are treated together.
465
466 reconsideration NOT required for peer-to-peer
467 "timer reconsideration" is
468 employed. This algorithm implements a simple back-off mechanism
469 which causes users to hold back RTCP packet transmission if the
470 group sizes are increasing.
471
472 n = number of members
473 C = avg_size/(rtcpBW/4)
474
475 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
476
477 4. The calculated interval T is set to a number uniformly distributed
478 between 0.5 and 1.5 times the deterministic calculated interval.
479
480 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
481 for the fact that the timer reconsideration algorithm converges to
482 a value of the RTCP bandwidth below the intended average
483*/
484
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000485 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000486
487 CriticalSectionScoped lock(_criticalSectionRTCPSender);
488
niklase@google.com470e71d2011-07-07 08:21:25 +0000489 if(_method == kRtcpOff)
490 {
491 return false;
492 }
493
niklase@google.com470e71d2011-07-07 08:21:25 +0000494 if(!_audio && sendKeyframeBeforeRTP)
495 {
496 // for video key-frames we want to send the RTCP before the large key-frame
497 // if we have a 100 ms margin
498 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
499 }
500
501 if(now > _nextTimeToSendRTCP)
502 {
503 return true;
504
505 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
506 {
507 // wrap
508 return true;
509 }
510 return false;
511}
512
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000513uint32_t
514RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000515{
516 CriticalSectionScoped lock(_criticalSectionRTCPSender);
517
518 lastRTCPTime = _lastRTCPTime[0];
519 return _lastSendReport[0];
520}
521
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000522uint32_t
523RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000524{
525 CriticalSectionScoped lock(_criticalSectionRTCPSender);
526
527 // This is only saved when we are the sender
528 if((_lastSendReport[0] == 0) || (sendReport == 0))
529 {
530 return 0; // will be ignored
531 } else
532 {
533 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
534 {
535 if( _lastSendReport[i] == sendReport)
536 {
537 return _lastRTCPTime[i];
538 }
539 }
540 }
541 return 0;
542}
543
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000544int32_t RTCPSender::AddReportBlock(const uint32_t SSRC,
545 const RTCPReportBlock* reportBlock) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000546 if (reportBlock == NULL) {
547 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
548 "%s invalid argument", __FUNCTION__);
549 return -1;
550 }
551 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000552
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000553 if (_reportBlocks.size() >= RTCP_MAX_REPORT_BLOCKS) {
554 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
555 "%s invalid argument", __FUNCTION__);
556 return -1;
557 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000558 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000559 _reportBlocks.find(SSRC);
560 if (it != _reportBlocks.end()) {
561 delete it->second;
562 _reportBlocks.erase(it);
563 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000564 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
565 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
566 _reportBlocks[SSRC] = copyReportBlock;
567 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000568}
569
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000570int32_t RTCPSender::RemoveReportBlock(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000571 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000572
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000573 std::map<uint32_t, RTCPReportBlock*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000574 _reportBlocks.find(SSRC);
575
576 if (it == _reportBlocks.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000577 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000578 }
579 delete it->second;
580 _reportBlocks.erase(it);
581 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000582}
583
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000584int32_t
585RTCPSender::BuildSR(uint8_t* rtcpbuffer,
586 uint32_t& pos,
587 const uint32_t NTPsec,
588 const uint32_t NTPfrac,
niklase@google.com470e71d2011-07-07 08:21:25 +0000589 const RTCPReportBlock* received)
590{
591 // sanity
592 if(pos + 52 >= IP_PACKET_SIZE)
593 {
594 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
595 return -2;
596 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000597 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000598
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000599 uint32_t posNumberOfReportBlocks = pos;
600 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000601
602 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000603 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000604
605 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
606 {
607 // shift old
608 _lastSendReport[i+1] = _lastSendReport[i];
609 _lastRTCPTime[i+1] =_lastRTCPTime[i];
610 }
611
stefan@webrtc.orgafcc6102013-04-09 13:37:40 +0000612 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000613 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000614
stefan@webrtc.orgafcc6102013-04-09 13:37:40 +0000615 if (!RtpTimestampNow(NTPsec, NTPfrac, &RTPtime)) {
616 RTPtime = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000617 }
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000618
niklase@google.com470e71d2011-07-07 08:21:25 +0000619
620 // Add sender data
621 // Save for our length field
622 pos++;
623 pos++;
624
625 // Add our own SSRC
626 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
627 pos += 4;
628 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000629 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000630 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000631 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000632 pos += 4;
633 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
634 pos += 4;
635
636 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000637 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000638 pos += 4;
639
640 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000641 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000642 pos += 4;
643
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000644 uint8_t numberOfReportBlocks = 0;
645 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000646 if(retVal < 0)
647 {
648 //
649 return retVal ;
650 }
651 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
652
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000653 uint16_t len = uint16_t((pos/4) -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000654 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
655 return 0;
656}
657
stefan@webrtc.orgafcc6102013-04-09 13:37:40 +0000658bool RTCPSender::RtpTimestampNow(uint32_t ntp_secs_now, uint32_t ntp_fracs_now,
659 uint32_t* timestamp_now) const {
660 if (last_frame_capture_time_ms_ < 0) {
661 return false;
662 }
663 uint32_t freq_khz = 90; // Default for video.
664 if(_audio) {
665 freq_khz = _rtpRtcp.CurrentSendFrequencyHz() / 1000;
666 }
667 // The timestamp of this RTCP packet should be estimated as the timestamp of
668 // the frame being captured at this moment. We are calculating that
669 // timestamp as the last frame's timestamp + the time since the last frame
670 // was captured.
671 *timestamp_now = start_timestamp_ + last_rtp_timestamp_ +
672 (Clock::NtpToMs(ntp_secs_now, ntp_fracs_now) -
673 last_frame_capture_time_ms_) * freq_khz;
674 return true;
675}
niklase@google.com470e71d2011-07-07 08:21:25 +0000676
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000677int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer,
678 uint32_t& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000679 size_t lengthCname = strlen(_CNAME);
680 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000681
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000682 // sanity
683 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
684 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
685 "%s invalid argument", __FUNCTION__);
686 return -2;
687 }
688 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000689
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000690 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000691 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
692 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000693
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000694 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000695 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000696 pos++;
697 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000698
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000699 // Add our own SSRC
700 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
701 pos += 4;
702
703 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000704 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000705
706 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000707 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000708
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000709 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000710
711 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
712 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000713 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000714
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000715 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000716 // We must have a zero field even if we have an even multiple of 4 bytes
717 if ((pos % 4) == 0) {
718 padding++;
719 rtcpbuffer[pos++]=0;
720 }
721 while ((pos % 4) != 0) {
722 padding++;
723 rtcpbuffer[pos++]=0;
724 }
725 SDESLength += padding;
726
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000727 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000728 _csrcCNAMEs.begin();
729
730 for(; it != _csrcCNAMEs.end(); it++) {
731 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000732 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000733
734 // Add SSRC
735 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000736 pos += 4;
737
738 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000739 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000740
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000741 size_t length = strlen(cname->name);
742 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000743
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000744 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000745 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000746
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000747 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000748
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000749 pos += length;
750 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000751 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000752
753 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000754 if((pos % 4) == 0){
755 padding++;
756 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000757 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000758 while((pos % 4) != 0){
759 padding++;
760 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000761 }
762 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000763 }
764 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000765 uint16_t buffer_length = (SDESLength / 4) - 1;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000766 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
767 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000768 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000769}
770
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000771int32_t
772RTCPSender::BuildRR(uint8_t* rtcpbuffer,
773 uint32_t& pos,
774 const uint32_t NTPsec,
775 const uint32_t NTPfrac,
niklase@google.com470e71d2011-07-07 08:21:25 +0000776 const RTCPReportBlock* received)
777{
778 // sanity one block
779 if(pos + 32 >= IP_PACKET_SIZE)
780 {
781 return -2;
782 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000783 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000784
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000785 rtcpbuffer[pos++]=(uint8_t)0x80;
786 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000787
788 // Save for our length field
789 pos++;
790 pos++;
791
792 // Add our own SSRC
793 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
794 pos += 4;
795
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000796 uint8_t numberOfReportBlocks = 0;
797 int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000798 if(retVal < 0)
799 {
800 return retVal;
801 }
802 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
803
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000804 uint16_t len = uint16_t((pos)/4 -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000805 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
806 return 0;
807}
808
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000809// From RFC 5450: Transmission Time Offsets in RTP Streams.
810// 0 1 2 3
811// 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
812// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
813// hdr |V=2|P| RC | PT=IJ=195 | length |
814// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
815// | inter-arrival jitter |
816// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
817// . .
818// . .
819// . .
820// | inter-arrival jitter |
821// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
822//
823// If present, this RTCP packet must be placed after a receiver report
824// (inside a compound RTCP packet), and MUST have the same value for RC
825// (reception report count) as the receiver report.
826
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000827int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000828RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000829 uint8_t* rtcpbuffer,
830 uint32_t& pos,
831 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000832{
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000833 if (_reportBlocks.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000834 {
835 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
836 return 0;
837 }
838
839 // sanity
840 if(pos + 8 >= IP_PACKET_SIZE)
841 {
842 return -2;
843 }
844 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000845 uint8_t RC = 1;
846 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
847 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000848
849 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000850 rtcpbuffer[pos++]=(uint8_t)0;
851 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000852
853 // Add inter-arrival jitter
854 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
855 jitterTransmissionTimeOffset);
856 pos += 4;
857 return 0;
858}
859
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000860int32_t
861RTCPSender::BuildPLI(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000862{
863 // sanity
864 if(pos + 12 >= IP_PACKET_SIZE)
865 {
866 return -2;
867 }
868 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000869 uint8_t FMT = 1;
870 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
871 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000872
873 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000874 rtcpbuffer[pos++]=(uint8_t)0;
875 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000876
877 // Add our own SSRC
878 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
879 pos += 4;
880
881 // Add the remote SSRC
882 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
883 pos += 4;
884 return 0;
885}
886
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000887int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
888 uint32_t& pos,
889 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000890 // sanity
891 if(pos + 20 >= IP_PACKET_SIZE) {
892 return -2;
893 }
894 if (!repeat) {
895 _sequenceNumberFIR++; // do not increase if repetition
896 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000897
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000898 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000899 uint8_t FMT = 4;
900 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
901 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000902
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000903 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000904 rtcpbuffer[pos++] = (uint8_t)0;
905 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000906
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000907 // Add our own SSRC
908 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
909 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000910
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000911 // RFC 5104 4.3.1.2. Semantics
912 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000913 rtcpbuffer[pos++] = (uint8_t)0;
914 rtcpbuffer[pos++] = (uint8_t)0;
915 rtcpbuffer[pos++] = (uint8_t)0;
916 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000917
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000918 // Additional Feedback Control Information (FCI)
919 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
920 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000921
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000922 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
923 rtcpbuffer[pos++] = (uint8_t)0;
924 rtcpbuffer[pos++] = (uint8_t)0;
925 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000926 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000927}
928
929/*
930 0 1 2 3
931 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
932 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
933 | First | Number | PictureID |
934 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
935*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000936int32_t
937RTCPSender::BuildSLI(uint8_t* rtcpbuffer, uint32_t& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000938{
939 // sanity
940 if(pos + 16 >= IP_PACKET_SIZE)
941 {
942 return -2;
943 }
944 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000945 uint8_t FMT = 2;
946 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
947 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000948
949 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000950 rtcpbuffer[pos++]=(uint8_t)0;
951 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000952
953 // Add our own SSRC
954 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
955 pos += 4;
956
957 // Add the remote SSRC
958 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
959 pos += 4;
960
961 // Add first, number & picture ID 6 bits
962 // first = 0, 13 - bits
963 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000964 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000965 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
966 pos += 4;
967 return 0;
968}
969
970/*
971 0 1 2 3
972 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
973 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
974 | PB |0| Payload Type| Native RPSI bit string |
975 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
976 | defined per codec ... | Padding (0) |
977 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
978*/
979/*
980* Note: not generic made for VP8
981*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000982int32_t
983RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
984 uint32_t& pos,
985 const uint64_t pictureID,
986 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +0000987{
988 // sanity
989 if(pos + 24 >= IP_PACKET_SIZE)
990 {
991 return -2;
992 }
993 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000994 uint8_t FMT = 3;
995 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
996 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000997
998 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000999 uint32_t bitsRequired = 7;
1000 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001001 while((pictureID>>bitsRequired) > 0)
1002 {
1003 bitsRequired += 7;
1004 bytesRequired++;
1005 }
1006
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001007 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001008 if(bytesRequired > 6)
1009 {
1010 size = 5;
1011 } else if(bytesRequired > 2)
1012 {
1013 size = 4;
1014 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001015 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001016 rtcpbuffer[pos++]=size;
1017
1018 // Add our own SSRC
1019 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1020 pos += 4;
1021
1022 // Add the remote SSRC
1023 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1024 pos += 4;
1025
1026 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001027 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001028 if(paddingBytes == 4)
1029 {
1030 paddingBytes = 0;
1031 }
1032 // add padding length in bits
1033 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1034 pos++;
1035
1036 // add payload type
1037 rtcpbuffer[pos] = payloadType;
1038 pos++;
1039
1040 // add picture ID
1041 for(int i = bytesRequired-1; i > 0; i--)
1042 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001043 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001044 pos++;
1045 }
1046 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001047 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001048 pos++;
1049
1050 // add padding
1051 for(int j = 0; j <paddingBytes; j++)
1052 {
1053 rtcpbuffer[pos] = 0;
1054 pos++;
1055 }
1056 return 0;
1057}
1058
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001059int32_t
1060RTCPSender::BuildREMB(uint8_t* rtcpbuffer, uint32_t& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001061{
1062 // sanity
1063 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1064 {
1065 return -2;
1066 }
1067 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001068 uint8_t FMT = 15;
1069 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1070 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001071
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001072 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001073 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1074
1075 // Add our own SSRC
1076 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1077 pos += 4;
1078
1079 // Remote SSRC must be 0
1080 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1081 pos += 4;
1082
1083 rtcpbuffer[pos++]='R';
1084 rtcpbuffer[pos++]='E';
1085 rtcpbuffer[pos++]='M';
1086 rtcpbuffer[pos++]='B';
1087
1088 rtcpbuffer[pos++] = _lengthRembSSRC;
1089 // 6 bit Exp
1090 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001091 uint8_t brExp = 0;
1092 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001093 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001094 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001095 {
1096 brExp = i;
1097 break;
1098 }
1099 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001100 const uint32_t brMantissa = (_rembBitrate >> brExp);
1101 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1102 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1103 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001104
1105 for (int i = 0; i < _lengthRembSSRC; i++)
1106 {
1107 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1108 pos += 4;
1109 }
edjee@google.com79b02892013-04-04 19:43:34 +00001110 TRACE_COUNTER1("webrtc_rtcp", "Remb", _rembBitrate);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001111 return 0;
1112}
1113
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001114void
1115RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001116{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001117 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001118 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001119}
1120
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001121int32_t
1122RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001123{
1124 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1125 // If the sender is an owner of the TMMBN -> send TMMBR
1126 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1127
niklase@google.com470e71d2011-07-07 08:21:25 +00001128 // get current bounding set from RTCP receiver
1129 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001130 // store in candidateSet, allocates one extra slot
1131 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001132
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001133 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1134 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1135 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001136 int32_t lengthOfBoundingSet
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001137 = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001138
1139 if(lengthOfBoundingSet > 0)
1140 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001141 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001142 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001143 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1144 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001145 {
1146 // do not send the same tuple
1147 return 0;
1148 }
1149 }
1150 if(!tmmbrOwner)
1151 {
1152 // use received bounding set as candidate set
1153 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001154 candidateSet->SetEntry(lengthOfBoundingSet,
1155 _tmmbr_Send,
1156 _packetOH_Send,
1157 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001158 int numCandidates = lengthOfBoundingSet+ 1;
1159
1160 // find bounding set
1161 TMMBRSet* boundingSet = NULL;
1162 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1163 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1164 {
1165 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1166 }
1167 if(!tmmbrOwner)
1168 {
1169 // did not enter bounding set, no meaning to send this request
1170 return 0;
1171 }
1172 }
1173 }
1174
1175 if(_tmmbr_Send)
1176 {
1177 // sanity
1178 if(pos + 20 >= IP_PACKET_SIZE)
1179 {
1180 return -2;
1181 }
1182 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001183 uint8_t FMT = 3;
1184 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1185 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001186
1187 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001188 rtcpbuffer[pos++]=(uint8_t)0;
1189 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001190
1191 // Add our own SSRC
1192 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1193 pos += 4;
1194
1195 // RFC 5104 4.2.1.2. Semantics
1196
1197 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001198 rtcpbuffer[pos++]=(uint8_t)0;
1199 rtcpbuffer[pos++]=(uint8_t)0;
1200 rtcpbuffer[pos++]=(uint8_t)0;
1201 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001202
1203 // Additional Feedback Control Information (FCI)
1204 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1205 pos += 4;
1206
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001207 uint32_t bitRate = _tmmbr_Send*1000;
1208 uint32_t mmbrExp = 0;
1209 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001210 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001211 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001212 {
1213 mmbrExp = i;
1214 break;
1215 }
1216 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001217 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001218
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001219 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1220 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1221 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1222 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001223 }
1224 return 0;
1225}
1226
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001227int32_t
1228RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001229{
1230 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1231 if(boundingSet == NULL)
1232 {
1233 return -1;
1234 }
1235 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001236 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001237 {
1238 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1239 return -2;
1240 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001241 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001242 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001243 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1244 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001245
1246 //Add length later
1247 int posLength = pos;
1248 pos++;
1249 pos++;
1250
1251 // Add our own SSRC
1252 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1253 pos += 4;
1254
1255 // RFC 5104 4.2.2.2. Semantics
1256
1257 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001258 rtcpbuffer[pos++]=(uint8_t)0;
1259 rtcpbuffer[pos++]=(uint8_t)0;
1260 rtcpbuffer[pos++]=(uint8_t)0;
1261 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001262
1263 // Additional Feedback Control Information (FCI)
1264 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001265 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001266 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001267 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001268 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001269 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001270 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1271 pos += 4;
1272
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001273 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1274 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001275 for(int i=0; i<64; i++)
1276 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001277 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001278 {
1279 mmbrExp = i;
1280 break;
1281 }
1282 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001283 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1284 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001285
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001286 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1287 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1288 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1289 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001290 numBoundingSet++;
1291 }
1292 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001293 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1294 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1295 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001296 return 0;
1297}
1298
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001299int32_t
1300RTCPSender::BuildAPP(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001301{
1302 // sanity
1303 if(_appData == NULL)
1304 {
1305 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1306 return -1;
1307 }
1308 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1309 {
1310 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1311 return -2;
1312 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001313 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001314
1315 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001316 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001317
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001318 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1319 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1320 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001321
1322 // Add our own SSRC
1323 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1324 pos += 4;
1325
1326 // Add our application name
1327 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1328 pos += 4;
1329
1330 // Add the data
1331 memcpy(rtcpbuffer +pos, _appData,_appLength);
1332 pos += _appLength;
1333 return 0;
1334}
1335
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001336int32_t
1337RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
1338 uint32_t& pos,
1339 const int32_t nackSize,
1340 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001341 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001342{
1343 // sanity
1344 if(pos + 16 >= IP_PACKET_SIZE)
1345 {
1346 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1347 return -2;
1348 }
1349
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001350 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001351 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001352 uint8_t FMT = 1;
1353 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1354 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001355
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001356 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001357 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001358 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001359
1360 // Add our own SSRC
1361 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1362 pos += 4;
1363
1364 // Add the remote SSRC
1365 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1366 pos += 4;
1367
1368 // add the list
1369 int i = 0;
1370 int numOfNackFields = 0;
edjee@google.com79b02892013-04-04 19:43:34 +00001371 NACKStringBuilder stringBuilder;
stefan@webrtc.orga2710702013-03-05 09:02:06 +00001372 while (nackSize > i && numOfNackFields < kRtcpMaxNackFields)
niklase@google.com470e71d2011-07-07 08:21:25 +00001373 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001374 uint16_t nack = nackList[i];
niklase@google.com470e71d2011-07-07 08:21:25 +00001375 // put dow our sequence number
1376 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, nack);
1377 pos += 2;
edjee@google.com79b02892013-04-04 19:43:34 +00001378 stringBuilder.PushNACK(nack);
niklase@google.com470e71d2011-07-07 08:21:25 +00001379
1380 i++;
1381 numOfNackFields++;
1382 if(nackSize > i)
1383 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001384 bool moreThan16Away = (uint16_t(nack+16) < nackList[i])?true: false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001385 if(!moreThan16Away)
1386 {
1387 // check for a wrap
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001388 if(uint16_t(nack+16) > 0xff00 && nackList[i] < 0x0fff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001389 {
1390 // wrap
1391 moreThan16Away = true;
1392 }
1393 }
1394 if(moreThan16Away)
1395 {
1396 // next is more than 16 away
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001397 rtcpbuffer[pos++]=(uint8_t)0;
1398 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001399 } else
1400 {
1401 // build our bitmask
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001402 uint16_t bitmask = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001403
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001404 bool within16Away = (uint16_t(nack+16) > nackList[i])?true: false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001405 if(within16Away)
1406 {
1407 // check for a wrap
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001408 if(uint16_t(nack+16) > 0xff00 && nackList[i] < 0x0fff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001409 {
1410 // wrap
1411 within16Away = false;
1412 }
1413 }
1414
1415 while( nackSize > i && within16Away)
1416 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001417 int16_t shift = (nackList[i]-nack)-1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001418 assert(!(shift > 15) && !(shift < 0));
1419
1420 bitmask += (1<< shift);
edjee@google.com79b02892013-04-04 19:43:34 +00001421 stringBuilder.PushNACK(nackList[i]);
niklase@google.com470e71d2011-07-07 08:21:25 +00001422 i++;
1423 if(nackSize > i)
1424 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001425 within16Away = (uint16_t(nack+16) > nackList[i])?true: false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001426 if(within16Away)
1427 {
1428 // check for a wrap
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001429 if(uint16_t(nack+16) > 0xff00 && nackList[i] < 0x0fff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001430 {
1431 // wrap
1432 within16Away = false;
1433 }
1434 }
1435 }
1436 }
1437 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, bitmask);
1438 pos += 2;
1439 }
1440 // sanity do we have room from one more 4 byte block?
1441 if(pos + 4 >= IP_PACKET_SIZE)
1442 {
1443 return -2;
1444 }
1445 } else
1446 {
1447 // no more in the list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001448 rtcpbuffer[pos++]=(uint8_t)0;
1449 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001450 }
1451 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001452 rtcpbuffer[nackSizePos]=(uint8_t)(2+numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001453 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001454 return 0;
1455}
1456
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001457int32_t
1458RTCPSender::BuildBYE(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001459{
1460 // sanity
1461 if(pos + 8 >= IP_PACKET_SIZE)
1462 {
1463 return -2;
1464 }
1465 if(_includeCSRCs)
1466 {
1467 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001468 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1469 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001470
1471 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001472 rtcpbuffer[pos++]=(uint8_t)0;
1473 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001474
1475 // Add our own SSRC
1476 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1477 pos += 4;
1478
1479 // add CSRCs
1480 for(int i = 0; i < _CSRCs; i++)
1481 {
1482 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1483 pos += 4;
1484 }
1485 } else
1486 {
1487 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001488 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1489 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001490
1491 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001492 rtcpbuffer[pos++]=(uint8_t)0;
1493 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001494
1495 // Add our own SSRC
1496 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1497 pos += 4;
1498 }
1499 return 0;
1500}
1501
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001502int32_t
1503RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, uint32_t& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001504{
1505 // sanity
1506 if(pos + 44 >= IP_PACKET_SIZE)
1507 {
1508 return -2;
1509 }
1510
1511 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001512 rtcpbuffer[pos++]=(uint8_t)0x80;
1513 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001514
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001515 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001516
1517 // handle length later on
1518 pos++;
1519 pos++;
1520
1521 // Add our own SSRC
1522 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1523 pos += 4;
1524
1525 // Add a VoIP metrics block
1526 rtcpbuffer[pos++]=7;
1527 rtcpbuffer[pos++]=0;
1528 rtcpbuffer[pos++]=0;
1529 rtcpbuffer[pos++]=8;
1530
1531 // Add the remote SSRC
1532 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1533 pos += 4;
1534
1535 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1536 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1537 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1538 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1539
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001540 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1541 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1542 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1543 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001544
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001545 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1546 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1547 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1548 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001549
1550 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1551 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1552 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1553 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1554
1555 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1556 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1557 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1558 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1559
1560 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1561 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001562 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1563 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001564
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001565 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1566 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1567 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1568 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001569
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001570 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1571 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001572 return 0;
1573}
1574
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001575int32_t
1576RTCPSender::SendRTCP(const uint32_t packetTypeFlags,
1577 const int32_t nackSize, // NACK
1578 const uint16_t* nackList, // NACK
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001579 const bool repeat, // FIR
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001580 const uint64_t pictureID) // SLI & RPSI
niklase@google.com470e71d2011-07-07 08:21:25 +00001581{
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001582 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1583 uint32_t pos = 0;
1584 uint8_t rtcpbuffer[IP_PACKET_SIZE];
niklase@google.com470e71d2011-07-07 08:21:25 +00001585
niklase@google.com470e71d2011-07-07 08:21:25 +00001586 do // only to be able to use break :) (and the critsect must be inside its own scope)
1587 {
1588 // collect the received information
1589 RTCPReportBlock received;
1590 bool hasReceived = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001591 uint32_t NTPsec = 0;
1592 uint32_t NTPfrac = 0;
xians@webrtc.org8738d272011-11-25 13:43:53 +00001593 bool rtcpCompound = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001594 uint32_t jitterTransmissionOffset = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001595
xians@webrtc.org8738d272011-11-25 13:43:53 +00001596 {
1597 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1598 if(_method == kRtcpOff)
1599 {
1600 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1601 "%s invalid state", __FUNCTION__);
1602 return -1;
1603 }
1604 rtcpCompound = (_method == kRtcpCompound) ? true : false;
1605 }
1606
1607 if (rtcpCompound ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001608 rtcpPacketTypeFlags & kRtcpReport ||
1609 rtcpPacketTypeFlags & kRtcpSr ||
1610 rtcpPacketTypeFlags & kRtcpRr)
1611 {
1612 // get statistics from our RTPreceiver outside critsect
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001613 if(_rtpRtcp.ReportBlockStatistics(&received.fractionLost,
1614 &received.cumulativeLost,
1615 &received.extendedHighSeqNum,
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001616 &received.jitter,
1617 &jitterTransmissionOffset) == 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001618 {
1619 hasReceived = true;
1620
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001621 uint32_t lastReceivedRRNTPsecs = 0;
1622 uint32_t lastReceivedRRNTPfrac = 0;
1623 uint32_t remoteSR = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001624
1625 // ok even if we have not received a SR, we will send 0 in that case
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001626 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1627 lastReceivedRRNTPfrac,
1628 remoteSR);
niklase@google.com470e71d2011-07-07 08:21:25 +00001629
1630 // get our NTP as late as possible to avoid a race
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001631 _clock->CurrentNtp(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001632
1633 // Delay since last received report
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001634 uint32_t delaySinceLastReceivedSR = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001635 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
1636 {
1637 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001638 uint32_t now=NTPsec&0x0000FFFF;
niklase@google.com470e71d2011-07-07 08:21:25 +00001639 now <<=16;
1640 now += (NTPfrac&0xffff0000)>>16;
1641
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001642 uint32_t receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
niklase@google.com470e71d2011-07-07 08:21:25 +00001643 receiveTime <<=16;
1644 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1645
1646 delaySinceLastReceivedSR = now-receiveTime;
1647 }
1648 received.delaySinceLastSR = delaySinceLastReceivedSR;
1649 received.lastSR = remoteSR;
1650 } else
1651 {
1652 // we need to send our NTP even if we dont have received any reports
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001653 _clock->CurrentNtp(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001654 }
1655 }
1656
1657 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1658
1659 if(_TMMBR ) // attach TMMBR to send and receive reports
1660 {
1661 rtcpPacketTypeFlags |= kRtcpTmmbr;
1662 }
1663 if(_appSend)
1664 {
1665 rtcpPacketTypeFlags |= kRtcpApp;
1666 _appSend = false;
1667 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001668 if(_REMB && _sendREMB)
1669 {
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +00001670 // Always attach REMB to SR if that is configured. Note that REMB is
1671 // only sent on one of the RTP modules in the REMB group.
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001672 rtcpPacketTypeFlags |= kRtcpRemb;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001673 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001674 if(_xrSendVoIPMetric)
1675 {
1676 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1677 _xrSendVoIPMetric = false;
1678 }
1679 if(_sendTMMBN) // set when having received a TMMBR
1680 {
1681 rtcpPacketTypeFlags |= kRtcpTmmbn;
1682 _sendTMMBN = false;
1683 }
1684
1685 if(_method == kRtcpCompound)
1686 {
1687 if(_sending)
1688 {
1689 rtcpPacketTypeFlags |= kRtcpSr;
1690 } else
1691 {
1692 rtcpPacketTypeFlags |= kRtcpRr;
1693 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001694 if (_IJ && hasReceived)
1695 {
1696 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1697 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001698 } else if(_method == kRtcpNonCompound)
1699 {
1700 if(rtcpPacketTypeFlags & kRtcpReport)
1701 {
1702 if(_sending)
1703 {
1704 rtcpPacketTypeFlags |= kRtcpSr;
1705 } else
1706 {
1707 rtcpPacketTypeFlags |= kRtcpRr;
1708 }
1709 }
1710 }
1711 if( rtcpPacketTypeFlags & kRtcpRr ||
1712 rtcpPacketTypeFlags & kRtcpSr)
1713 {
1714 // generate next time to send a RTCP report
1715 // seeded from RTP constructor
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001716 int32_t random = rand() % 1000;
1717 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
niklase@google.com470e71d2011-07-07 08:21:25 +00001718
1719 if(_audio)
1720 {
1721 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
1722 }else
1723 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001724 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
niklase@google.com470e71d2011-07-07 08:21:25 +00001725 if(_sending)
1726 {
1727 // calc bw for video 360/sendBW in kbit/s
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001728 uint32_t sendBitrateKbit = 0;
1729 uint32_t videoRate = 0;
1730 uint32_t fecRate = 0;
1731 uint32_t nackRate = 0;
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001732 _rtpRtcp.BitrateSent(&sendBitrateKbit,
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001733 &videoRate,
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001734 &fecRate,
1735 &nackRate);
1736 sendBitrateKbit /= 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001737 if(sendBitrateKbit != 0)
1738 {
1739 minIntervalMs = 360000/sendBitrateKbit;
1740 }
1741 }
1742 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1743 {
1744 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1745 }
1746 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1747 }
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001748 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
niklase@google.com470e71d2011-07-07 08:21:25 +00001749 }
1750
1751 // if the data does not fitt in the packet we fill it as much as possible
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001752 int32_t buildVal = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001753
1754 if(rtcpPacketTypeFlags & kRtcpSr)
1755 {
1756 if(hasReceived)
1757 {
1758 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
1759 } else
1760 {
1761 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac);
1762 }
1763 if(buildVal == -1)
1764 {
1765 return -1; // error
1766
1767 }else if(buildVal == -2)
1768 {
1769 break; // out of buffer
1770 }
1771 buildVal = BuildSDEC(rtcpbuffer, pos);
1772 if(buildVal == -1)
1773 {
1774 return -1; // error
1775
1776 }else if(buildVal == -2)
1777 {
1778 break; // out of buffer
1779 }
1780
1781 }else if(rtcpPacketTypeFlags & kRtcpRr)
1782 {
1783 if(hasReceived)
1784 {
1785 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
1786 }else
1787 {
1788 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
1789 }
1790 if(buildVal == -1)
1791 {
1792 return -1; // error
1793
1794 }else if(buildVal == -2)
1795 {
1796 break; // out of buffer
1797 }
1798 // only of set
1799 if(_CNAME[0] != 0)
1800 {
1801 buildVal = BuildSDEC(rtcpbuffer, pos);
1802 if(buildVal == -1)
1803 {
1804 return -1; // error
1805 }
1806 }
1807 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001808 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1809 {
1810 // If present, this RTCP packet must be placed after a
1811 // receiver report.
1812 buildVal = BuildExtendedJitterReport(rtcpbuffer,
1813 pos,
1814 jitterTransmissionOffset);
1815 if(buildVal == -1)
1816 {
1817 return -1; // error
1818 }
1819 else if(buildVal == -2)
1820 {
1821 break; // out of buffer
1822 }
1823 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001824 if(rtcpPacketTypeFlags & kRtcpPli)
1825 {
1826 buildVal = BuildPLI(rtcpbuffer, pos);
1827 if(buildVal == -1)
1828 {
1829 return -1; // error
1830
1831 }else if(buildVal == -2)
1832 {
1833 break; // out of buffer
1834 }
edjee@google.com79b02892013-04-04 19:43:34 +00001835 TRACE_EVENT_INSTANT1("webrtc_rtcp", "SendRTCP", "type", "pli");
1836 _pliCount++;
1837 TRACE_COUNTER1("webrtc_rtcp", "PLI Count", _pliCount);
niklase@google.com470e71d2011-07-07 08:21:25 +00001838 }
1839 if(rtcpPacketTypeFlags & kRtcpFir)
1840 {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001841 buildVal = BuildFIR(rtcpbuffer, pos, repeat);
niklase@google.com470e71d2011-07-07 08:21:25 +00001842 if(buildVal == -1)
1843 {
1844 return -1; // error
1845
1846 }else if(buildVal == -2)
1847 {
1848 break; // out of buffer
1849 }
edjee@google.com79b02892013-04-04 19:43:34 +00001850 TRACE_EVENT_INSTANT1("webrtc_rtcp", "SendRTCP", "type", "fir");
1851 _fullIntraRequestCount++;
1852 TRACE_COUNTER1("webrtc_rtcp", "FIR Count", _fullIntraRequestCount);
niklase@google.com470e71d2011-07-07 08:21:25 +00001853 }
1854 if(rtcpPacketTypeFlags & kRtcpSli)
1855 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001856 buildVal = BuildSLI(rtcpbuffer, pos, (uint8_t)pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +00001857 if(buildVal == -1)
1858 {
1859 return -1; // error
1860
1861 }else if(buildVal == -2)
1862 {
1863 break; // out of buffer
1864 }
1865 }
1866 if(rtcpPacketTypeFlags & kRtcpRpsi)
1867 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001868 const int8_t payloadType = _rtpRtcp.SendPayloadType();
niklase@google.com470e71d2011-07-07 08:21:25 +00001869 if(payloadType == -1)
1870 {
1871 return -1;
1872 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001873 buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (uint8_t)payloadType);
niklase@google.com470e71d2011-07-07 08:21:25 +00001874 if(buildVal == -1)
1875 {
1876 return -1; // error
1877
1878 }else if(buildVal == -2)
1879 {
1880 break; // out of buffer
1881 }
1882 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001883 if(rtcpPacketTypeFlags & kRtcpRemb)
1884 {
1885 buildVal = BuildREMB(rtcpbuffer, pos);
1886 if(buildVal == -1)
1887 {
1888 return -1; // error
1889
1890 }else if(buildVal == -2)
1891 {
1892 break; // out of buffer
1893 }
edjee@google.com79b02892013-04-04 19:43:34 +00001894 TRACE_EVENT_INSTANT2("webrtc_rtcp", "SendRTCP", "type", "remb",
1895 "bitrate", _rembBitrate);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001896 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001897 if(rtcpPacketTypeFlags & kRtcpBye)
1898 {
1899 buildVal = BuildBYE(rtcpbuffer, pos);
1900 if(buildVal == -1)
1901 {
1902 return -1; // error
1903
1904 }else if(buildVal == -2)
1905 {
1906 break; // out of buffer
1907 }
1908 }
1909 if(rtcpPacketTypeFlags & kRtcpApp)
1910 {
1911 buildVal = BuildAPP(rtcpbuffer, pos);
1912 if(buildVal == -1)
1913 {
1914 return -1; // error
1915
1916 }else if(buildVal == -2)
1917 {
1918 break; // out of buffer
1919 }
1920 }
1921 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1922 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001923 buildVal = BuildTMMBR(rtcpbuffer, pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001924 if(buildVal == -1)
1925 {
1926 return -1; // error
1927
1928 }else if(buildVal == -2)
1929 {
1930 break; // out of buffer
1931 }
1932 }
1933 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1934 {
1935 buildVal = BuildTMMBN(rtcpbuffer, pos);
1936 if(buildVal == -1)
1937 {
1938 return -1; // error
1939
1940 }else if(buildVal == -2)
1941 {
1942 break; // out of buffer
1943 }
1944 }
1945 if(rtcpPacketTypeFlags & kRtcpNack)
1946 {
edjee@google.com79b02892013-04-04 19:43:34 +00001947 std::string nackString;
1948 buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList,
1949 &nackString);
niklase@google.com470e71d2011-07-07 08:21:25 +00001950 if(buildVal == -1)
1951 {
1952 return -1; // error
1953
1954 }else if(buildVal == -2)
1955 {
1956 break; // out of buffer
1957 }
edjee@google.com79b02892013-04-04 19:43:34 +00001958 TRACE_EVENT_INSTANT2("webrtc_rtcp", "SendRTCP", "type", "nack",
1959 "list", TRACE_STR_COPY(nackString.c_str()));
1960 _nackCount++;
1961 TRACE_COUNTER1("webrtc_rtcp", "Nacks", _nackCount);
niklase@google.com470e71d2011-07-07 08:21:25 +00001962 }
1963 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1964 {
1965 buildVal = BuildVoIPMetric(rtcpbuffer, pos);
1966 if(buildVal == -1)
1967 {
1968 return -1; // error
1969
1970 }else if(buildVal == -2)
1971 {
1972 break; // out of buffer
1973 }
1974 }
1975 }while (false);
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001976 // Sanity don't send empty packets.
1977 if (pos == 0)
1978 {
1979 return -1;
1980 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001981 return SendToNetwork(rtcpbuffer, (uint16_t)pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001982}
1983
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001984int32_t
1985RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
1986 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001987{
1988 CriticalSectionScoped lock(_criticalSectionTransport);
1989 if(_cbTransport)
1990 {
1991 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1992 {
1993 return 0;
1994 }
1995 }
1996 return -1;
1997}
1998
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001999int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002000RTCPSender::SetCSRCStatus(const bool include)
2001{
2002 _includeCSRCs = include;
2003 return 0;
2004}
2005
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002006int32_t
2007RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
2008 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00002009{
2010 if(arrLength > kRtpCsrcSize)
2011 {
2012 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2013 assert(false);
2014 return -1;
2015 }
2016
2017 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2018
2019 for(int i = 0; i < arrLength;i++)
2020 {
2021 _CSRC[i] = arrOfCSRC[i];
2022 }
2023 _CSRCs = arrLength;
2024 return 0;
2025}
2026
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002027int32_t
2028RTCPSender::SetApplicationSpecificData(const uint8_t subType,
2029 const uint32_t name,
2030 const uint8_t* data,
2031 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002032{
2033 if(length %4 != 0)
2034 {
2035 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2036 return -1;
2037 }
2038 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2039
2040 if(_appData)
2041 {
2042 delete [] _appData;
2043 }
2044
2045 _appSend = true;
2046 _appSubType = subType;
2047 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002048 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002049 _appLength = length;
2050 memcpy(_appData, data, length);
2051 return 0;
2052}
2053
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002054int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002055RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2056{
2057 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2058 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2059
2060 _xrSendVoIPMetric = true;
2061 return 0;
2062}
2063
2064// called under critsect _criticalSectionRTCPSender
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002065int32_t RTCPSender::AddReportBlocks(uint8_t* rtcpbuffer,
2066 uint32_t& pos,
2067 uint8_t& numberOfReportBlocks,
2068 const RTCPReportBlock* received,
2069 const uint32_t NTPsec,
2070 const uint32_t NTPfrac) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002071 // sanity one block
2072 if(pos + 24 >= IP_PACKET_SIZE) {
2073 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2074 "%s invalid argument", __FUNCTION__);
2075 return -1;
2076 }
2077 numberOfReportBlocks = _reportBlocks.size();
2078 if (received) {
2079 // add our multiple RR to numberOfReportBlocks
2080 numberOfReportBlocks++;
2081 }
2082 if (received) {
2083 // answer to the one that sends to me
stefan@webrtc.orgafcc6102013-04-09 13:37:40 +00002084 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002085
2086 // Remote SSRC
2087 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
2088 pos += 4;
2089
2090 // fraction lost
2091 rtcpbuffer[pos++]=received->fractionLost;
2092
2093 // cumulative loss
2094 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2095 received->cumulativeLost);
2096 pos += 3;
2097 // extended highest seq_no, contain the highest sequence number received
2098 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2099 received->extendedHighSeqNum);
2100 pos += 4;
2101
2102 //Jitter
2103 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
2104 pos += 4;
2105
2106 // Last SR timestamp, our NTP time when we received the last report
2107 // This is the value that we read from the send report packet not when we
2108 // received it...
2109 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
2110 pos += 4;
2111
2112 // Delay since last received report,time since we received the report
2113 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2114 received->delaySinceLastSR);
2115 pos += 4;
2116 }
2117 if ((pos + _reportBlocks.size() * 24) >= IP_PACKET_SIZE) {
2118 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2119 "%s invalid argument", __FUNCTION__);
2120 return -1;
2121 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002122 std::map<uint32_t, RTCPReportBlock*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002123 _reportBlocks.begin();
2124
2125 for (; it != _reportBlocks.end(); it++) {
2126 // we can have multiple report block in a conference
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002127 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002128 RTCPReportBlock* reportBlock = it->second;
2129 if (reportBlock) {
2130 // Remote SSRC
2131 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
2132 pos += 4;
2133
2134 // fraction lost
2135 rtcpbuffer[pos++] = reportBlock->fractionLost;
2136
2137 // cumulative loss
2138 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2139 reportBlock->cumulativeLost);
2140 pos += 3;
2141
2142 // extended highest seq_no, contain the highest sequence number received
2143 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2144 reportBlock->extendedHighSeqNum);
2145 pos += 4;
2146
2147 //Jitter
2148 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2149 reportBlock->jitter);
2150 pos += 4;
2151
2152 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2153 reportBlock->lastSR);
2154 pos += 4;
2155
2156 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2157 reportBlock->delaySinceLastSR);
2158 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002159 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002160 }
2161 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00002162}
2163
2164// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002165int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002166RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002167 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002168{
2169 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2170
2171 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2172 {
2173 _sendTMMBN = true;
2174 return 0;
2175 }
2176 return -1;
2177}
niklase@google.com470e71d2011-07-07 08:21:25 +00002178} // namespace webrtc