blob: 551e1c5598e3bd3f988c07674696a5772839b344 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> // assert
14#include <stdlib.h> // rand
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000015#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000017#include <algorithm> // min
18
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000019#include "webrtc/common_types.h"
20#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
21#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
22#include "webrtc/system_wrappers/interface/trace.h"
23#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000024
niklase@google.com470e71d2011-07-07 08:21:25 +000025namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000026
27using RTCPUtility::RTCPCnameInformation;
28
edjee@google.com79b02892013-04-04 19:43:34 +000029NACKStringBuilder::NACKStringBuilder() :
30 _stream(""), _count(0), _consecutive(false)
31{
32 // Empty.
33}
34
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000035NACKStringBuilder::~NACKStringBuilder() {}
36
pbos@webrtc.org2f446732013-04-08 11:08:41 +000037void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000038{
39 if (_count == 0)
40 {
41 _stream << nack;
42 } else if (nack == _prevNack + 1)
43 {
44 _consecutive = true;
45 } else
46 {
47 if (_consecutive)
48 {
49 _stream << "-" << _prevNack;
50 _consecutive = false;
51 }
52 _stream << "," << nack;
53 }
54 _count++;
55 _prevNack = nack;
56}
57
58std::string NACKStringBuilder::GetResult()
59{
60 if (_consecutive)
61 {
62 _stream << "-" << _prevNack;
63 _consecutive = false;
64 }
65 return _stream.str();
66}
67
pbos@webrtc.org2f446732013-04-08 11:08:41 +000068RTCPSender::RTCPSender(const int32_t id,
niklase@google.com470e71d2011-07-07 08:21:25 +000069 const bool audio,
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000070 Clock* clock,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000071 ModuleRtpRtcpImpl* owner,
72 ReceiveStatistics* receive_statistics) :
niklase@google.com470e71d2011-07-07 08:21:25 +000073 _id(id),
74 _audio(audio),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000075 _clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000076 _method(kRtcpOff),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000077 _rtpRtcp(*owner),
henrike@webrtc.org65573f22011-12-13 19:17:27 +000078 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000079 _cbTransport(NULL),
80
henrike@webrtc.org65573f22011-12-13 19:17:27 +000081 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000082 _usingNack(false),
83 _sending(false),
84 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000085 _REMB(false),
86 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000087 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +000088 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000089 _nextTimeToSendRTCP(0),
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000090 start_timestamp_(0),
91 last_rtp_timestamp_(0),
92 last_frame_capture_time_ms_(-1),
niklase@google.com470e71d2011-07-07 08:21:25 +000093 _SSRC(0),
94 _remoteSSRC(0),
95 _CNAME(),
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000096 receive_statistics_(receive_statistics),
97 internal_report_blocks_(),
98 external_report_blocks_(),
niklase@google.com470e71d2011-07-07 08:21:25 +000099 _csrcCNAMEs(),
100
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000101 _cameraDelayMS(0),
102
niklase@google.com470e71d2011-07-07 08:21:25 +0000103 _lastSendReport(),
104 _lastRTCPTime(),
105
106 _CSRCs(0),
107 _CSRC(),
108 _includeCSRCs(true),
109
110 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000111
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000112 _lengthRembSSRC(0),
113 _sizeRembSSRC(0),
114 _rembSSRC(NULL),
115 _rembBitrate(0),
116
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000117 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000118 _tmmbr_Send(0),
119 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000120
121 _appSend(false),
122 _appSubType(0),
123 _appName(),
124 _appData(NULL),
125 _appLength(0),
126 _xrSendVoIPMetric(false),
edjee@google.com79b02892013-04-04 19:43:34 +0000127 _xrVoIPMetric(),
128 _nackCount(0),
129 _pliCount(0),
130 _fullIntraRequestCount(0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000131{
132 memset(_CNAME, 0, sizeof(_CNAME));
133 memset(_lastSendReport, 0, sizeof(_lastSendReport));
134 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
135
136 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
137}
138
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000139RTCPSender::~RTCPSender() {
140 delete [] _rembSSRC;
141 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000142
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000143 while (!internal_report_blocks_.empty()) {
144 delete internal_report_blocks_.begin()->second;
145 internal_report_blocks_.erase(internal_report_blocks_.begin());
146 }
147 while (!external_report_blocks_.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000148 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000149 external_report_blocks_.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000150 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000151 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000152 }
153 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000154 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000155 _csrcCNAMEs.begin();
156 delete it->second;
157 _csrcCNAMEs.erase(it);
158 }
159 delete _criticalSectionTransport;
160 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000161
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000162 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000163}
164
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000165int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000166RTCPSender::Init()
167{
168 CriticalSectionScoped lock(_criticalSectionRTCPSender);
169
170 _method = kRtcpOff;
171 _cbTransport = NULL;
172 _usingNack = false;
173 _sending = false;
174 _sendTMMBN = false;
175 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000176 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000177 _REMB = false;
178 _sendREMB = false;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000179 last_rtp_timestamp_ = 0;
180 last_frame_capture_time_ms_ = -1;
181 start_timestamp_ = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000182 _SSRC = 0;
183 _remoteSSRC = 0;
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000184 _cameraDelayMS = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000185 _sequenceNumberFIR = 0;
186 _tmmbr_Send = 0;
187 _packetOH_Send = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000188 _nextTimeToSendRTCP = 0;
189 _CSRCs = 0;
190 _appSend = false;
191 _appSubType = 0;
192
193 if(_appData)
194 {
195 delete [] _appData;
196 _appData = NULL;
197 }
198 _appLength = 0;
199
200 _xrSendVoIPMetric = false;
201
202 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
203 memset(_CNAME, 0, sizeof(_CNAME));
204 memset(_lastSendReport, 0, sizeof(_lastSendReport));
205 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
edjee@google.com79b02892013-04-04 19:43:34 +0000206
207 _nackCount = 0;
208 _pliCount = 0;
209 _fullIntraRequestCount = 0;
210
niklase@google.com470e71d2011-07-07 08:21:25 +0000211 return 0;
212}
213
214void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000215RTCPSender::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +0000216{
217 _id = id;
218}
219
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000220int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000221RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
222{
223 CriticalSectionScoped lock(_criticalSectionTransport);
224 _cbTransport = outgoingTransport;
225 return 0;
226}
227
228RTCPMethod
229RTCPSender::Status() const
230{
231 CriticalSectionScoped lock(_criticalSectionRTCPSender);
232 return _method;
233}
234
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000235int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000236RTCPSender::SetRTCPStatus(const RTCPMethod method)
237{
238 CriticalSectionScoped lock(_criticalSectionRTCPSender);
239 if(method != kRtcpOff)
240 {
241 if(_audio)
242 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000243 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000244 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000245 } else
246 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000247 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000248 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000249 }
250 }
251 _method = method;
252 return 0;
253}
254
255bool
256RTCPSender::Sending() const
257{
258 CriticalSectionScoped lock(_criticalSectionRTCPSender);
259 return _sending;
260}
261
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000262int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000263RTCPSender::SetSendingStatus(const bool sending)
264{
265 bool sendRTCPBye = false;
266 {
267 CriticalSectionScoped lock(_criticalSectionRTCPSender);
268
269 if(_method != kRtcpOff)
270 {
271 if(sending == false && _sending == true)
272 {
273 // Trigger RTCP bye
274 sendRTCPBye = true;
275 }
276 }
277 _sending = sending;
278 }
279 if(sendRTCPBye)
280 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000281 return SendRTCP(kRtcpBye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000282 }
283 return 0;
284}
285
286bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000287RTCPSender::REMB() const
288{
289 CriticalSectionScoped lock(_criticalSectionRTCPSender);
290 return _REMB;
291}
292
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000293int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000294RTCPSender::SetREMBStatus(const bool enable)
295{
296 CriticalSectionScoped lock(_criticalSectionRTCPSender);
297 _REMB = enable;
298 return 0;
299}
300
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000301int32_t
302RTCPSender::SetREMBData(const uint32_t bitrate,
303 const uint8_t numberOfSSRC,
304 const uint32_t* SSRC)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000305{
306 CriticalSectionScoped lock(_criticalSectionRTCPSender);
307 _rembBitrate = bitrate;
308
309 if(_sizeRembSSRC < numberOfSSRC)
310 {
311 delete [] _rembSSRC;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000312 _rembSSRC = new uint32_t[numberOfSSRC];
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000313 _sizeRembSSRC = numberOfSSRC;
314 }
315
316 _lengthRembSSRC = numberOfSSRC;
317 for (int i = 0; i < numberOfSSRC; i++)
318 {
319 _rembSSRC[i] = SSRC[i];
320 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000321 _sendREMB = true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000322 return 0;
323}
324
325bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000326RTCPSender::TMMBR() const
327{
328 CriticalSectionScoped lock(_criticalSectionRTCPSender);
329 return _TMMBR;
330}
331
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000332int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000333RTCPSender::SetTMMBRStatus(const bool enable)
334{
335 CriticalSectionScoped lock(_criticalSectionRTCPSender);
336 _TMMBR = enable;
337 return 0;
338}
339
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000340bool
341RTCPSender::IJ() const
342{
343 CriticalSectionScoped lock(_criticalSectionRTCPSender);
344 return _IJ;
345}
346
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000347int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000348RTCPSender::SetIJStatus(const bool enable)
349{
350 CriticalSectionScoped lock(_criticalSectionRTCPSender);
351 _IJ = enable;
352 return 0;
353}
354
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000355void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
356 start_timestamp_ = start_timestamp;
357}
358
359void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
360 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000361 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000362 last_rtp_timestamp_ = rtp_timestamp;
363 if (capture_time_ms < 0) {
364 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000365 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000366 } else {
367 last_frame_capture_time_ms_ = capture_time_ms;
368 }
369}
370
niklase@google.com470e71d2011-07-07 08:21:25 +0000371void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000372RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000373{
374 CriticalSectionScoped lock(_criticalSectionRTCPSender);
375
376 if(_SSRC != 0)
377 {
378 // not first SetSSRC, probably due to a collision
379 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000380 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000381 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000382 }
383 _SSRC = ssrc;
384}
385
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000386void RTCPSender::SetRemoteSSRC(uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000387{
388 CriticalSectionScoped lock(_criticalSectionRTCPSender);
389 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000390}
391
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000392int32_t
393RTCPSender::SetCameraDelay(const int32_t delayMS)
394{
395 CriticalSectionScoped lock(_criticalSectionRTCPSender);
396 if(delayMS > 1000 || delayMS < -1000)
397 {
398 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
399 return -1;
400 }
401 _cameraDelayMS = delayMS;
402 return 0;
403}
404
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000405int32_t RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000406 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000407 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000408 cName[RTCP_CNAME_SIZE - 1] = 0;
409 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000410 return 0;
411}
412
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000413int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000414 if (!cName)
415 return -1;
416
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000417 CriticalSectionScoped lock(_criticalSectionRTCPSender);
418 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
419 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
420 return 0;
421}
422
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000423int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
424 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000425 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000426 CriticalSectionScoped lock(_criticalSectionRTCPSender);
427 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
428 return -1;
429 }
430 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000431 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
432 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000433 _csrcCNAMEs[SSRC] = ptr;
434 return 0;
435}
436
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000437int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000438 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000439 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000440 _csrcCNAMEs.find(SSRC);
441
442 if (it == _csrcCNAMEs.end()) {
443 return -1;
444 }
445 delete it->second;
446 _csrcCNAMEs.erase(it);
447 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000448}
449
450bool
451RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
452{
453/*
454 For audio we use a fix 5 sec interval
455
456 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
457 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
458
459
460From RFC 3550
461
462 MAX RTCP BW is 5% if the session BW
463 A send report is approximately 65 bytes inc CNAME
464 A report report is approximately 28 bytes
465
466 The RECOMMENDED value for the reduced minimum in seconds is 360
467 divided by the session bandwidth in kilobits/second. This minimum
468 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
469
470 If the participant has not yet sent an RTCP packet (the variable
471 initial is true), the constant Tmin is set to 2.5 seconds, else it
472 is set to 5 seconds.
473
474 The interval between RTCP packets is varied randomly over the
475 range [0.5,1.5] times the calculated interval to avoid unintended
476 synchronization of all participants
477
478 if we send
479 If the participant is a sender (we_sent true), the constant C is
480 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
481 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
482 number of senders.
483
484 if we receive only
485 If we_sent is not true, the constant C is set
486 to the average RTCP packet size divided by 75% of the RTCP
487 bandwidth. The constant n is set to the number of receivers
488 (members - senders). If the number of senders is greater than
489 25%, senders and receivers are treated together.
490
491 reconsideration NOT required for peer-to-peer
492 "timer reconsideration" is
493 employed. This algorithm implements a simple back-off mechanism
494 which causes users to hold back RTCP packet transmission if the
495 group sizes are increasing.
496
497 n = number of members
498 C = avg_size/(rtcpBW/4)
499
500 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
501
502 4. The calculated interval T is set to a number uniformly distributed
503 between 0.5 and 1.5 times the deterministic calculated interval.
504
505 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
506 for the fact that the timer reconsideration algorithm converges to
507 a value of the RTCP bandwidth below the intended average
508*/
509
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000510 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000511
512 CriticalSectionScoped lock(_criticalSectionRTCPSender);
513
niklase@google.com470e71d2011-07-07 08:21:25 +0000514 if(_method == kRtcpOff)
515 {
516 return false;
517 }
518
niklase@google.com470e71d2011-07-07 08:21:25 +0000519 if(!_audio && sendKeyframeBeforeRTP)
520 {
521 // for video key-frames we want to send the RTCP before the large key-frame
522 // if we have a 100 ms margin
523 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
524 }
525
526 if(now > _nextTimeToSendRTCP)
527 {
528 return true;
529
530 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
531 {
532 // wrap
533 return true;
534 }
535 return false;
536}
537
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000538uint32_t
539RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000540{
541 CriticalSectionScoped lock(_criticalSectionRTCPSender);
542
543 lastRTCPTime = _lastRTCPTime[0];
544 return _lastSendReport[0];
545}
546
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000547uint32_t
548RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000549{
550 CriticalSectionScoped lock(_criticalSectionRTCPSender);
551
552 // This is only saved when we are the sender
553 if((_lastSendReport[0] == 0) || (sendReport == 0))
554 {
555 return 0; // will be ignored
556 } else
557 {
558 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
559 {
560 if( _lastSendReport[i] == sendReport)
561 {
562 return _lastRTCPTime[i];
563 }
564 }
565 }
566 return 0;
567}
568
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000569int32_t RTCPSender::AddExternalReportBlock(
570 uint32_t SSRC,
571 const RTCPReportBlock* reportBlock) {
572 CriticalSectionScoped lock(_criticalSectionRTCPSender);
573 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
574}
575
576int32_t RTCPSender::AddReportBlock(
577 uint32_t SSRC,
578 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
579 const RTCPReportBlock* reportBlock) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000580 if (reportBlock == NULL) {
581 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
582 "%s invalid argument", __FUNCTION__);
583 return -1;
584 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000585
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000586 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000587 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
588 "%s invalid argument", __FUNCTION__);
589 return -1;
590 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000591 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000592 report_blocks->find(SSRC);
593 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000594 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000595 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000596 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000597 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
598 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000599 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000600 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000601}
602
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000603int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000604 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000605
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000606 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000607 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000608
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000609 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000610 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000611 }
612 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000613 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000614 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000615}
616
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000617int32_t
618RTCPSender::BuildSR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000619 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000620 const uint32_t NTPsec,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000621 const uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000622{
623 // sanity
624 if(pos + 52 >= IP_PACKET_SIZE)
625 {
626 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
627 return -2;
628 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000629 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000630
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000631 uint32_t posNumberOfReportBlocks = pos;
632 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000633
634 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000635 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000636
637 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
638 {
639 // shift old
640 _lastSendReport[i+1] = _lastSendReport[i];
641 _lastRTCPTime[i+1] =_lastRTCPTime[i];
642 }
643
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000644 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000645 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000646
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000647 uint32_t freqHz = 90000; // For video
648 if(_audio) {
649 freqHz = _rtpRtcp.CurrentSendFrequencyHz();
niklase@google.com470e71d2011-07-07 08:21:25 +0000650 }
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000651
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000652 // The timestamp of this RTCP packet should be estimated as the timestamp of
653 // the frame being captured at this moment. We are calculating that
654 // timestamp as the last frame's timestamp + the time since the last frame
655 // was captured.
656 {
657 // Needs protection since this method is called on the process thread.
658 CriticalSectionScoped lock(_criticalSectionRTCPSender);
659 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
660 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
661 (freqHz / 1000);
662 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000663
664 // Add sender data
665 // Save for our length field
666 pos++;
667 pos++;
668
669 // Add our own SSRC
670 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
671 pos += 4;
672 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000673 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000674 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000675 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000676 pos += 4;
677 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
678 pos += 4;
679
680 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000681 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000682 pos += 4;
683
684 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000685 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000686 pos += 4;
687
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000688 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000689 int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
690 numberOfReportBlocks,
691 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000692 if(retVal < 0)
693 {
694 //
695 return retVal ;
696 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000697 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000698 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
699
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000700 uint16_t len = uint16_t((pos/4) -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000701 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
702 return 0;
703}
704
705
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000706int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000707 size_t lengthCname = strlen(_CNAME);
708 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000709
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000710 // sanity
711 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
712 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
713 "%s invalid argument", __FUNCTION__);
714 return -2;
715 }
716 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000717
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000718 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000719 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
720 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000721
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000722 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000723 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000724 pos++;
725 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000726
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000727 // Add our own SSRC
728 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
729 pos += 4;
730
731 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000732 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000733
734 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000735 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000736
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000737 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000738
739 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
740 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000741 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000742
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000743 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000744 // We must have a zero field even if we have an even multiple of 4 bytes
745 if ((pos % 4) == 0) {
746 padding++;
747 rtcpbuffer[pos++]=0;
748 }
749 while ((pos % 4) != 0) {
750 padding++;
751 rtcpbuffer[pos++]=0;
752 }
753 SDESLength += padding;
754
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000755 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000756 _csrcCNAMEs.begin();
757
758 for(; it != _csrcCNAMEs.end(); it++) {
759 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000760 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000761
762 // Add SSRC
763 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000764 pos += 4;
765
766 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000767 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000768
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000769 size_t length = strlen(cname->name);
770 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000771
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000772 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000773 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000774
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000775 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000776
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000777 pos += length;
778 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000779 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000780
781 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000782 if((pos % 4) == 0){
783 padding++;
784 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000785 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000786 while((pos % 4) != 0){
787 padding++;
788 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000789 }
790 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000791 }
792 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000793 uint16_t buffer_length = (SDESLength / 4) - 1;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000794 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
795 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000796 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000797}
798
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000799int32_t
800RTCPSender::BuildRR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000801 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000802 const uint32_t NTPsec,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000803 const uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000804{
805 // sanity one block
806 if(pos + 32 >= IP_PACKET_SIZE)
807 {
808 return -2;
809 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000810 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000811
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000812 rtcpbuffer[pos++]=(uint8_t)0x80;
813 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000814
815 // Save for our length field
816 pos++;
817 pos++;
818
819 // Add our own SSRC
820 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
821 pos += 4;
822
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000823 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000824 int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
825 numberOfReportBlocks,
826 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000827 if(retVal < 0)
828 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000829 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000830 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000831 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000832 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
833
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000834 uint16_t len = uint16_t((pos)/4 -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000835 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
836 return 0;
837}
838
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000839// From RFC 5450: Transmission Time Offsets in RTP Streams.
840// 0 1 2 3
841// 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
842// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
843// hdr |V=2|P| RC | PT=IJ=195 | length |
844// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
845// | inter-arrival jitter |
846// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
847// . .
848// . .
849// . .
850// | inter-arrival jitter |
851// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
852//
853// If present, this RTCP packet must be placed after a receiver report
854// (inside a compound RTCP packet), and MUST have the same value for RC
855// (reception report count) as the receiver report.
856
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000857int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000858RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000859 uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000860 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000861 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000862{
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000863 if (external_report_blocks_.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000864 {
865 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
866 return 0;
867 }
868
869 // sanity
870 if(pos + 8 >= IP_PACKET_SIZE)
871 {
872 return -2;
873 }
874 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000875 uint8_t RC = 1;
876 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
877 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000878
879 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000880 rtcpbuffer[pos++]=(uint8_t)0;
881 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000882
883 // Add inter-arrival jitter
884 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
885 jitterTransmissionTimeOffset);
886 pos += 4;
887 return 0;
888}
889
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000890int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000891RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000892{
893 // sanity
894 if(pos + 12 >= IP_PACKET_SIZE)
895 {
896 return -2;
897 }
898 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000899 uint8_t FMT = 1;
900 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
901 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000902
903 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000904 rtcpbuffer[pos++]=(uint8_t)0;
905 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000906
907 // Add our own SSRC
908 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
909 pos += 4;
910
911 // Add the remote SSRC
912 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
913 pos += 4;
914 return 0;
915}
916
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000917int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000918 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000919 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000920 // sanity
921 if(pos + 20 >= IP_PACKET_SIZE) {
922 return -2;
923 }
924 if (!repeat) {
925 _sequenceNumberFIR++; // do not increase if repetition
926 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000927
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000928 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000929 uint8_t FMT = 4;
930 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
931 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000932
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000933 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000934 rtcpbuffer[pos++] = (uint8_t)0;
935 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000936
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000937 // Add our own SSRC
938 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
939 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000940
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000941 // RFC 5104 4.3.1.2. Semantics
942 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000943 rtcpbuffer[pos++] = (uint8_t)0;
944 rtcpbuffer[pos++] = (uint8_t)0;
945 rtcpbuffer[pos++] = (uint8_t)0;
946 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000947
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000948 // Additional Feedback Control Information (FCI)
949 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
950 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000951
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000952 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
953 rtcpbuffer[pos++] = (uint8_t)0;
954 rtcpbuffer[pos++] = (uint8_t)0;
955 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000956 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000957}
958
959/*
960 0 1 2 3
961 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
962 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
963 | First | Number | PictureID |
964 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
965*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000966int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000967RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000968{
969 // sanity
970 if(pos + 16 >= IP_PACKET_SIZE)
971 {
972 return -2;
973 }
974 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000975 uint8_t FMT = 2;
976 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
977 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000978
979 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000980 rtcpbuffer[pos++]=(uint8_t)0;
981 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000982
983 // Add our own SSRC
984 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
985 pos += 4;
986
987 // Add the remote SSRC
988 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
989 pos += 4;
990
991 // Add first, number & picture ID 6 bits
992 // first = 0, 13 - bits
993 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000994 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000995 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
996 pos += 4;
997 return 0;
998}
999
1000/*
1001 0 1 2 3
1002 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
1003 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1004 | PB |0| Payload Type| Native RPSI bit string |
1005 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1006 | defined per codec ... | Padding (0) |
1007 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1008*/
1009/*
1010* Note: not generic made for VP8
1011*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001012int32_t
1013RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001014 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001015 const uint64_t pictureID,
1016 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +00001017{
1018 // sanity
1019 if(pos + 24 >= IP_PACKET_SIZE)
1020 {
1021 return -2;
1022 }
1023 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001024 uint8_t FMT = 3;
1025 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1026 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001027
1028 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001029 uint32_t bitsRequired = 7;
1030 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001031 while((pictureID>>bitsRequired) > 0)
1032 {
1033 bitsRequired += 7;
1034 bytesRequired++;
1035 }
1036
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001037 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001038 if(bytesRequired > 6)
1039 {
1040 size = 5;
1041 } else if(bytesRequired > 2)
1042 {
1043 size = 4;
1044 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001045 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001046 rtcpbuffer[pos++]=size;
1047
1048 // Add our own SSRC
1049 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1050 pos += 4;
1051
1052 // Add the remote SSRC
1053 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1054 pos += 4;
1055
1056 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001057 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001058 if(paddingBytes == 4)
1059 {
1060 paddingBytes = 0;
1061 }
1062 // add padding length in bits
1063 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1064 pos++;
1065
1066 // add payload type
1067 rtcpbuffer[pos] = payloadType;
1068 pos++;
1069
1070 // add picture ID
1071 for(int i = bytesRequired-1; i > 0; i--)
1072 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001073 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001074 pos++;
1075 }
1076 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001077 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001078 pos++;
1079
1080 // add padding
1081 for(int j = 0; j <paddingBytes; j++)
1082 {
1083 rtcpbuffer[pos] = 0;
1084 pos++;
1085 }
1086 return 0;
1087}
1088
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001089int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001090RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001091{
1092 // sanity
1093 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1094 {
1095 return -2;
1096 }
1097 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001098 uint8_t FMT = 15;
1099 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1100 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001101
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001102 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001103 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1104
1105 // Add our own SSRC
1106 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1107 pos += 4;
1108
1109 // Remote SSRC must be 0
1110 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1111 pos += 4;
1112
1113 rtcpbuffer[pos++]='R';
1114 rtcpbuffer[pos++]='E';
1115 rtcpbuffer[pos++]='M';
1116 rtcpbuffer[pos++]='B';
1117
1118 rtcpbuffer[pos++] = _lengthRembSSRC;
1119 // 6 bit Exp
1120 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001121 uint8_t brExp = 0;
1122 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001123 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001124 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001125 {
1126 brExp = i;
1127 break;
1128 }
1129 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001130 const uint32_t brMantissa = (_rembBitrate >> brExp);
1131 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1132 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1133 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001134
1135 for (int i = 0; i < _lengthRembSSRC; i++)
1136 {
1137 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1138 pos += 4;
1139 }
1140 return 0;
1141}
1142
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001143void
1144RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001145{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001146 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001147 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001148}
1149
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001150int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001151RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001152{
1153 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1154 // If the sender is an owner of the TMMBN -> send TMMBR
1155 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1156
niklase@google.com470e71d2011-07-07 08:21:25 +00001157 // get current bounding set from RTCP receiver
1158 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001159 // store in candidateSet, allocates one extra slot
1160 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001161
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001162 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1163 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1164 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001165 int32_t lengthOfBoundingSet
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001166 = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001167
1168 if(lengthOfBoundingSet > 0)
1169 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001170 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001171 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001172 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1173 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001174 {
1175 // do not send the same tuple
1176 return 0;
1177 }
1178 }
1179 if(!tmmbrOwner)
1180 {
1181 // use received bounding set as candidate set
1182 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001183 candidateSet->SetEntry(lengthOfBoundingSet,
1184 _tmmbr_Send,
1185 _packetOH_Send,
1186 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001187 int numCandidates = lengthOfBoundingSet+ 1;
1188
1189 // find bounding set
1190 TMMBRSet* boundingSet = NULL;
1191 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1192 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1193 {
1194 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1195 }
1196 if(!tmmbrOwner)
1197 {
1198 // did not enter bounding set, no meaning to send this request
1199 return 0;
1200 }
1201 }
1202 }
1203
1204 if(_tmmbr_Send)
1205 {
1206 // sanity
1207 if(pos + 20 >= IP_PACKET_SIZE)
1208 {
1209 return -2;
1210 }
1211 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001212 uint8_t FMT = 3;
1213 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1214 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001215
1216 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001217 rtcpbuffer[pos++]=(uint8_t)0;
1218 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001219
1220 // Add our own SSRC
1221 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1222 pos += 4;
1223
1224 // RFC 5104 4.2.1.2. Semantics
1225
1226 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001227 rtcpbuffer[pos++]=(uint8_t)0;
1228 rtcpbuffer[pos++]=(uint8_t)0;
1229 rtcpbuffer[pos++]=(uint8_t)0;
1230 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001231
1232 // Additional Feedback Control Information (FCI)
1233 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1234 pos += 4;
1235
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001236 uint32_t bitRate = _tmmbr_Send*1000;
1237 uint32_t mmbrExp = 0;
1238 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001239 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001240 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001241 {
1242 mmbrExp = i;
1243 break;
1244 }
1245 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001246 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001247
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001248 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1249 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1250 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1251 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001252 }
1253 return 0;
1254}
1255
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001256int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001257RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001258{
1259 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1260 if(boundingSet == NULL)
1261 {
1262 return -1;
1263 }
1264 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001265 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001266 {
1267 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1268 return -2;
1269 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001270 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001271 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001272 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1273 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001274
1275 //Add length later
1276 int posLength = pos;
1277 pos++;
1278 pos++;
1279
1280 // Add our own SSRC
1281 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1282 pos += 4;
1283
1284 // RFC 5104 4.2.2.2. Semantics
1285
1286 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001287 rtcpbuffer[pos++]=(uint8_t)0;
1288 rtcpbuffer[pos++]=(uint8_t)0;
1289 rtcpbuffer[pos++]=(uint8_t)0;
1290 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001291
1292 // Additional Feedback Control Information (FCI)
1293 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001294 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001295 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001296 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001297 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001298 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001299 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1300 pos += 4;
1301
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001302 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1303 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001304 for(int i=0; i<64; i++)
1305 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001306 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001307 {
1308 mmbrExp = i;
1309 break;
1310 }
1311 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001312 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1313 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001314
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001315 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1316 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1317 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1318 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001319 numBoundingSet++;
1320 }
1321 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001322 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1323 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1324 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001325 return 0;
1326}
1327
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001328int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001329RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001330{
1331 // sanity
1332 if(_appData == NULL)
1333 {
1334 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1335 return -1;
1336 }
1337 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1338 {
1339 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1340 return -2;
1341 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001342 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001343
1344 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001345 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001346
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001347 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1348 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1349 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001350
1351 // Add our own SSRC
1352 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1353 pos += 4;
1354
1355 // Add our application name
1356 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1357 pos += 4;
1358
1359 // Add the data
1360 memcpy(rtcpbuffer +pos, _appData,_appLength);
1361 pos += _appLength;
1362 return 0;
1363}
1364
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001365int32_t
1366RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001367 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001368 const int32_t nackSize,
1369 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001370 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001371{
1372 // sanity
1373 if(pos + 16 >= IP_PACKET_SIZE)
1374 {
1375 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1376 return -2;
1377 }
1378
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001379 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001380 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001381 uint8_t FMT = 1;
1382 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1383 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001384
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001385 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001386 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001387 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001388
1389 // Add our own SSRC
1390 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1391 pos += 4;
1392
1393 // Add the remote SSRC
1394 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1395 pos += 4;
1396
edjee@google.com79b02892013-04-04 19:43:34 +00001397 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001398 // Build NACK bitmasks and write them to the RTCP message.
1399 // The nack list should be sorted and not contain duplicates if one
1400 // wants to build the smallest rtcp nack packet.
1401 int numOfNackFields = 0;
1402 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1403 (IP_PACKET_SIZE - pos) / 4);
1404 int i = 0;
1405 while (i < nackSize && numOfNackFields < maxNackFields) {
1406 stringBuilder.PushNACK(nackList[i]);
1407 uint16_t nack = nackList[i++];
1408 uint16_t bitmask = 0;
1409 while (i < nackSize) {
1410 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1411 if (shift >= 0 && shift <= 15) {
1412 stringBuilder.PushNACK(nackList[i]);
1413 bitmask |= (1 << shift);
1414 ++i;
1415 } else {
1416 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001417 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001418 }
1419 // Write the sequence number and the bitmask to the packet.
1420 assert(pos + 4 < IP_PACKET_SIZE);
1421 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
1422 pos += 2;
1423 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
1424 pos += 2;
1425 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001426 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001427 if (i != nackSize) {
1428 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1429 "Nack list to large for one packet.");
1430 }
1431 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001432 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001433 return 0;
1434}
1435
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001436int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001437RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001438{
1439 // sanity
1440 if(pos + 8 >= IP_PACKET_SIZE)
1441 {
1442 return -2;
1443 }
1444 if(_includeCSRCs)
1445 {
1446 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001447 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1448 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001449
1450 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001451 rtcpbuffer[pos++]=(uint8_t)0;
1452 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001453
1454 // Add our own SSRC
1455 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1456 pos += 4;
1457
1458 // add CSRCs
1459 for(int i = 0; i < _CSRCs; i++)
1460 {
1461 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1462 pos += 4;
1463 }
1464 } else
1465 {
1466 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001467 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1468 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001469
1470 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001471 rtcpbuffer[pos++]=(uint8_t)0;
1472 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001473
1474 // Add our own SSRC
1475 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1476 pos += 4;
1477 }
1478 return 0;
1479}
1480
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001481int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001482RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001483{
1484 // sanity
1485 if(pos + 44 >= IP_PACKET_SIZE)
1486 {
1487 return -2;
1488 }
1489
1490 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001491 rtcpbuffer[pos++]=(uint8_t)0x80;
1492 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001493
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001494 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001495
1496 // handle length later on
1497 pos++;
1498 pos++;
1499
1500 // Add our own SSRC
1501 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1502 pos += 4;
1503
1504 // Add a VoIP metrics block
1505 rtcpbuffer[pos++]=7;
1506 rtcpbuffer[pos++]=0;
1507 rtcpbuffer[pos++]=0;
1508 rtcpbuffer[pos++]=8;
1509
1510 // Add the remote SSRC
1511 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1512 pos += 4;
1513
1514 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1515 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1516 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1517 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1518
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001519 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1520 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1521 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1522 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001523
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001524 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1525 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1526 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1527 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001528
1529 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1530 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1531 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1532 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1533
1534 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1535 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1536 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1537 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1538
1539 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1540 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001541 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1542 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001543
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001544 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1545 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1546 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1547 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001548
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001549 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1550 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001551 return 0;
1552}
1553
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001554int32_t
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001555RTCPSender::SendRTCP(
1556 uint32_t packetTypeFlags,
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001557 int32_t nackSize,
1558 const uint16_t* nackList,
1559 bool repeat,
1560 uint64_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +00001561{
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001562 {
1563 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1564 if(_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001565 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001566 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1567 "%s invalid state", __FUNCTION__);
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001568 return -1;
1569 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001570 }
1571 uint8_t rtcp_buffer[IP_PACKET_SIZE];
1572 int rtcp_length = PrepareRTCP(packetTypeFlags, nackSize, nackList, repeat,
1573 pictureID, rtcp_buffer, IP_PACKET_SIZE);
1574 if (rtcp_length < 0) {
1575 return -1;
1576 }
1577 // Sanity don't send empty packets.
1578 if (rtcp_length == 0)
1579 {
1580 return -1;
1581 }
1582 return SendToNetwork(rtcp_buffer, static_cast<uint16_t>(rtcp_length));
1583}
1584
1585int RTCPSender::PrepareRTCP(
1586 uint32_t packetTypeFlags,
1587 int32_t nackSize,
1588 const uint16_t* nackList,
1589 bool repeat,
1590 uint64_t pictureID,
1591 uint8_t* rtcp_buffer,
1592 int buffer_size) {
1593 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1594 // Collect the received information.
1595 uint32_t NTPsec = 0;
1596 uint32_t NTPfrac = 0;
1597 uint32_t jitterTransmissionOffset = 0;
1598 int position = 0;
1599
1600 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1601
1602 if(_TMMBR ) // Attach TMMBR to send and receive reports.
1603 {
1604 rtcpPacketTypeFlags |= kRtcpTmmbr;
1605 }
1606 if(_appSend)
1607 {
1608 rtcpPacketTypeFlags |= kRtcpApp;
1609 _appSend = false;
1610 }
1611 if(_REMB && _sendREMB)
1612 {
1613 // Always attach REMB to SR if that is configured. Note that REMB is
1614 // only sent on one of the RTP modules in the REMB group.
1615 rtcpPacketTypeFlags |= kRtcpRemb;
1616 }
1617 if(_xrSendVoIPMetric)
1618 {
1619 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1620 _xrSendVoIPMetric = false;
1621 }
1622 if(_sendTMMBN) // Set when having received a TMMBR.
1623 {
1624 rtcpPacketTypeFlags |= kRtcpTmmbn;
1625 _sendTMMBN = false;
1626 }
1627
1628 if(_method == kRtcpCompound)
1629 {
1630 if(_sending)
1631 {
1632 rtcpPacketTypeFlags |= kRtcpSr;
1633 } else
1634 {
1635 rtcpPacketTypeFlags |= kRtcpRr;
1636 }
1637 } else if(_method == kRtcpNonCompound)
1638 {
1639 if(rtcpPacketTypeFlags & kRtcpReport)
1640 {
1641 if(_sending)
1642 {
1643 rtcpPacketTypeFlags |= kRtcpSr;
1644 } else
1645 {
1646 rtcpPacketTypeFlags |= kRtcpRr;
1647 }
1648 }
1649 }
1650 if( rtcpPacketTypeFlags & kRtcpRr ||
1651 rtcpPacketTypeFlags & kRtcpSr)
1652 {
1653 // generate next time to send a RTCP report
1654 // seeded from RTP constructor
1655 int32_t random = rand() % 1000;
1656 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1657
1658 if(_audio)
1659 {
1660 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1661 (RTCP_INTERVAL_AUDIO_MS*random/1000);
1662 }else
1663 {
1664 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1665 if(_sending)
1666 {
1667 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1668 uint32_t sendBitrateKbit = 0;
1669 uint32_t videoRate = 0;
1670 uint32_t fecRate = 0;
1671 uint32_t nackRate = 0;
1672 _rtpRtcp.BitrateSent(&sendBitrateKbit,
1673 &videoRate,
1674 &fecRate,
1675 &nackRate);
1676 sendBitrateKbit /= 1000;
1677 if(sendBitrateKbit != 0)
1678 {
1679 minIntervalMs = 360000/sendBitrateKbit;
1680 }
1681 }
1682 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1683 {
1684 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1685 }
1686 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1687 }
1688 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1689 }
1690
1691 // If the data does not fit in the packet we fill it as much as possible.
1692 int32_t buildVal = 0;
1693
1694 // We need to send our NTP even if we haven't received any reports.
1695 _clock->CurrentNtp(NTPsec, NTPfrac);
1696 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1697 StatisticianMap statisticians =
1698 receive_statistics_->GetActiveStatisticians();
1699 if (!statisticians.empty()) {
1700 StatisticianMap::const_iterator it;
1701 int i;
1702 for (it = statisticians.begin(), i = 0; it != statisticians.end();
1703 ++it, ++i) {
1704 RTCPReportBlock report_block;
1705 if (PrepareReport(it->second, &report_block, &NTPsec, &NTPfrac))
1706 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1707 }
1708 if (_IJ && !statisticians.empty()) {
1709 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1710 }
1711 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
1712 }
1713 }
1714
1715 if(rtcpPacketTypeFlags & kRtcpSr)
1716 {
1717 buildVal = BuildSR(rtcp_buffer, position, NTPsec, NTPfrac);
1718 if (buildVal == -1) {
1719 return -1;
1720 } else if (buildVal == -2) {
1721 return position;
1722 }
1723 buildVal = BuildSDEC(rtcp_buffer, position);
1724 if (buildVal == -1) {
1725 return -1;
1726 } else if (buildVal == -2) {
1727 return position;
1728 }
1729 }else if(rtcpPacketTypeFlags & kRtcpRr)
1730 {
1731 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1732 if (buildVal == -1) {
1733 return -1;
1734 } else if (buildVal == -2) {
1735 return position;
1736 }
1737 // only of set
1738 if(_CNAME[0] != 0)
1739 {
1740 buildVal = BuildSDEC(rtcp_buffer, position);
1741 if (buildVal == -1) {
1742 return -1;
1743 }
1744 }
1745 }
1746 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1747 {
1748 // If present, this RTCP packet must be placed after a
1749 // receiver report.
1750 buildVal = BuildExtendedJitterReport(rtcp_buffer,
1751 position,
1752 jitterTransmissionOffset);
1753 if (buildVal == -1) {
1754 return -1;
1755 } else if (buildVal == -2) {
1756 return position;
1757 }
1758 }
1759 if(rtcpPacketTypeFlags & kRtcpPli)
1760 {
1761 buildVal = BuildPLI(rtcp_buffer, position);
1762 if (buildVal == -1) {
1763 return -1;
1764 } else if (buildVal == -2) {
1765 return position;
1766 }
1767 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
1768 _pliCount++;
1769 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC, _pliCount);
1770 }
1771 if(rtcpPacketTypeFlags & kRtcpFir)
1772 {
1773 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1774 if (buildVal == -1) {
1775 return -1;
1776 } else if (buildVal == -2) {
1777 return position;
1778 }
1779 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
1780 _fullIntraRequestCount++;
1781 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
1782 _fullIntraRequestCount);
1783 }
1784 if(rtcpPacketTypeFlags & kRtcpSli)
1785 {
1786 buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1787 if (buildVal == -1) {
1788 return -1;
1789 } else if (buildVal == -2) {
1790 return position;
1791 }
1792 }
1793 if(rtcpPacketTypeFlags & kRtcpRpsi)
1794 {
1795 const int8_t payloadType = _rtpRtcp.SendPayloadType();
1796 if (payloadType == -1) {
1797 return -1;
1798 }
1799 buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1800 (uint8_t)payloadType);
1801 if (buildVal == -1) {
1802 return -1;
1803 } else if (buildVal == -2) {
1804 return position;
1805 }
1806 }
1807 if(rtcpPacketTypeFlags & kRtcpRemb)
1808 {
1809 buildVal = BuildREMB(rtcp_buffer, position);
1810 if (buildVal == -1) {
1811 return -1;
1812 } else if (buildVal == -2) {
1813 return position;
1814 }
1815 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1816 }
1817 if(rtcpPacketTypeFlags & kRtcpBye)
1818 {
1819 buildVal = BuildBYE(rtcp_buffer, position);
1820 if (buildVal == -1) {
1821 return -1;
1822 } else if (buildVal == -2) {
1823 return position;
1824 }
1825 }
1826 if(rtcpPacketTypeFlags & kRtcpApp)
1827 {
1828 buildVal = BuildAPP(rtcp_buffer, position);
1829 if (buildVal == -1) {
1830 return -1;
1831 } else if (buildVal == -2) {
1832 return position;
1833 }
1834 }
1835 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1836 {
1837 buildVal = BuildTMMBR(rtcp_buffer, position);
1838 if (buildVal == -1) {
1839 return -1;
1840 } else if (buildVal == -2) {
1841 return position;
1842 }
1843 }
1844 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1845 {
1846 buildVal = BuildTMMBN(rtcp_buffer, position);
1847 if (buildVal == -1) {
1848 return -1;
1849 } else if (buildVal == -2) {
1850 return position;
1851 }
1852 }
1853 if(rtcpPacketTypeFlags & kRtcpNack)
1854 {
1855 std::string nackString;
1856 buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
1857 &nackString);
1858 if (buildVal == -1) {
1859 return -1;
1860 } else if (buildVal == -2) {
1861 return position;
1862 }
1863 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
1864 "nacks", TRACE_STR_COPY(nackString.c_str()));
1865 _nackCount++;
1866 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC, _nackCount);
1867 }
1868 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1869 {
1870 buildVal = BuildVoIPMetric(rtcp_buffer, position);
1871 if (buildVal == -1) {
1872 return -1;
1873 } else if (buildVal == -2) {
1874 return position;
1875 }
1876 }
1877 return position;
1878}
1879
1880bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
1881 return Status() == kRtcpCompound ||
1882 (rtcp_packet_type & kRtcpReport) ||
1883 (rtcp_packet_type & kRtcpSr) ||
1884 (rtcp_packet_type & kRtcpRr);
1885}
1886
1887bool RTCPSender::PrepareReport(StreamStatistician* statistician,
1888 RTCPReportBlock* report_block,
1889 uint32_t* ntp_secs, uint32_t* ntp_frac) {
1890 // Do we have receive statistics to send?
1891 StreamStatistician::Statistics stats;
1892 if (!statistician->GetStatistics(&stats, true))
1893 return false;
1894 report_block->fractionLost = stats.fraction_lost;
1895 report_block->cumulativeLost = stats.cumulative_lost;
1896 report_block->extendedHighSeqNum =
1897 stats.extended_max_sequence_number;
1898 report_block->jitter = stats.jitter;
1899
1900 uint32_t lastReceivedRRNTPsecs = 0;
1901 uint32_t lastReceivedRRNTPfrac = 0;
1902 uint32_t remoteSR = 0;
1903
1904 // ok even if we have not received a SR, we will send 0 in that case
1905 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1906 lastReceivedRRNTPfrac,
1907 remoteSR);
1908
1909 // get our NTP as late as possible to avoid a race
1910 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
1911
1912 // Delay since last received report
1913 uint32_t delaySinceLastReceivedSR = 0;
1914 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0)) {
1915 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1916 uint32_t now=*ntp_secs&0x0000FFFF;
1917 now <<=16;
1918 now += (*ntp_frac&0xffff0000)>>16;
1919
1920 uint32_t receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
1921 receiveTime <<=16;
1922 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1923
1924 delaySinceLastReceivedSR = now-receiveTime;
1925 }
1926 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
1927 report_block->lastSR = remoteSR;
1928 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001929}
1930
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001931int32_t
1932RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
1933 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001934{
1935 CriticalSectionScoped lock(_criticalSectionTransport);
1936 if(_cbTransport)
1937 {
1938 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1939 {
1940 return 0;
1941 }
1942 }
1943 return -1;
1944}
1945
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001946int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00001947RTCPSender::SetCSRCStatus(const bool include)
1948{
1949 _includeCSRCs = include;
1950 return 0;
1951}
1952
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001953int32_t
1954RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
1955 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00001956{
1957 if(arrLength > kRtpCsrcSize)
1958 {
1959 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1960 assert(false);
1961 return -1;
1962 }
1963
1964 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1965
1966 for(int i = 0; i < arrLength;i++)
1967 {
1968 _CSRC[i] = arrOfCSRC[i];
1969 }
1970 _CSRCs = arrLength;
1971 return 0;
1972}
1973
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001974int32_t
1975RTCPSender::SetApplicationSpecificData(const uint8_t subType,
1976 const uint32_t name,
1977 const uint8_t* data,
1978 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001979{
1980 if(length %4 != 0)
1981 {
1982 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1983 return -1;
1984 }
1985 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1986
1987 if(_appData)
1988 {
1989 delete [] _appData;
1990 }
1991
1992 _appSend = true;
1993 _appSubType = subType;
1994 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001995 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00001996 _appLength = length;
1997 memcpy(_appData, data, length);
1998 return 0;
1999}
2000
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002001int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002002RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2003{
2004 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2005 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2006
2007 _xrSendVoIPMetric = true;
2008 return 0;
2009}
2010
2011// called under critsect _criticalSectionRTCPSender
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002012int32_t RTCPSender::WriteAllReportBlocksToBuffer(
2013 uint8_t* rtcpbuffer,
2014 int pos,
2015 uint8_t& numberOfReportBlocks,
2016 const uint32_t NTPsec,
2017 const uint32_t NTPfrac) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002018 // sanity one block
2019 if(pos + 24 >= IP_PACKET_SIZE) {
2020 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2021 "%s invalid argument", __FUNCTION__);
2022 return -1;
2023 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002024 numberOfReportBlocks = external_report_blocks_.size();
2025 numberOfReportBlocks += internal_report_blocks_.size();
2026 if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002027 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2028 "%s invalid argument", __FUNCTION__);
2029 return -1;
2030 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002031 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2032 while (!internal_report_blocks_.empty()) {
2033 delete internal_report_blocks_.begin()->second;
2034 internal_report_blocks_.erase(internal_report_blocks_.begin());
2035 }
2036 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2037 return pos;
2038}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002039
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002040int32_t RTCPSender::WriteReportBlocksToBuffer(
2041 uint8_t* rtcpbuffer,
2042 int32_t position,
2043 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2044 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2045 report_blocks.begin();
2046 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002047 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002048 RTCPReportBlock* reportBlock = it->second;
2049 if (reportBlock) {
2050 // Remote SSRC
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002051 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position, remoteSSRC);
2052 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002053
2054 // fraction lost
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002055 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002056
2057 // cumulative loss
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002058 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002059 reportBlock->cumulativeLost);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002060 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002061
2062 // extended highest seq_no, contain the highest sequence number received
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002063 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002064 reportBlock->extendedHighSeqNum);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002065 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002066
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002067 // Jitter
2068 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002069 reportBlock->jitter);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002070 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002071
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002072 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002073 reportBlock->lastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002074 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002075
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002076 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002077 reportBlock->delaySinceLastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002078 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002079 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002080 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002081 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00002082}
2083
2084// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002085int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002086RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002087 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002088{
2089 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2090
2091 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2092 {
2093 _sendTMMBN = true;
2094 return 0;
2095 }
2096 return -1;
2097}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002098} // namespace webrtc