blob: 6d81d95963d227100c61d6ce3f677a8efc0c44ee [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.org59f20bb2013-09-09 16:02:19 +000068RTCPSender::FeedbackState::FeedbackState(ModuleRtpRtcpImpl* module)
69 : send_payload_type(module->SendPayloadType()),
70 frequency_hz(module->CurrentSendFrequencyHz()),
71 packet_count_sent(module->PacketCountSent()),
72 byte_count_sent(module->ByteCountSent()),
73 module(module) {
74 uint32_t last_ntp_secs = 0, last_ntp_frac = 0, last_remote_sr = 0;
75 module->LastReceivedNTP(last_ntp_secs, last_ntp_frac, last_remote_sr);
76 last_rr_ntp_secs = last_ntp_secs;
77 last_rr_ntp_frac = last_ntp_frac;
78 remote_sr = last_remote_sr;
79
80 uint32_t send_bitrate = 0, tmp;
81 module->BitrateSent(&send_bitrate, &tmp, &tmp, &tmp);
82 this->send_bitrate = send_bitrate;
83}
84
85RTCPSender::FeedbackState::FeedbackState()
86 : send_payload_type(0),
87 frequency_hz(0),
88 packet_count_sent(0),
89 byte_count_sent(0),
90 send_bitrate(0),
91 last_rr_ntp_secs(0),
92 last_rr_ntp_frac(0),
93 remote_sr(0) {}
94
pbos@webrtc.org2f446732013-04-08 11:08:41 +000095RTCPSender::RTCPSender(const int32_t id,
niklase@google.com470e71d2011-07-07 08:21:25 +000096 const bool audio,
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000097 Clock* clock,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000098 ReceiveStatistics* receive_statistics) :
niklase@google.com470e71d2011-07-07 08:21:25 +000099 _id(id),
100 _audio(audio),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000101 _clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +0000102 _method(kRtcpOff),
henrike@webrtc.org65573f22011-12-13 19:17:27 +0000103 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +0000104 _cbTransport(NULL),
105
henrike@webrtc.org65573f22011-12-13 19:17:27 +0000106 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +0000107 _usingNack(false),
108 _sending(false),
109 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000110 _REMB(false),
111 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000112 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000113 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000114 _nextTimeToSendRTCP(0),
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000115 start_timestamp_(0),
116 last_rtp_timestamp_(0),
117 last_frame_capture_time_ms_(-1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000118 _SSRC(0),
119 _remoteSSRC(0),
120 _CNAME(),
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000121 receive_statistics_(receive_statistics),
122 internal_report_blocks_(),
123 external_report_blocks_(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000124 _csrcCNAMEs(),
125
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000126 _cameraDelayMS(0),
127
niklase@google.com470e71d2011-07-07 08:21:25 +0000128 _lastSendReport(),
129 _lastRTCPTime(),
130
131 _CSRCs(0),
132 _CSRC(),
133 _includeCSRCs(true),
134
135 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000136
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000137 _lengthRembSSRC(0),
138 _sizeRembSSRC(0),
139 _rembSSRC(NULL),
140 _rembBitrate(0),
141
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000142 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000143 _tmmbr_Send(0),
144 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000145
146 _appSend(false),
147 _appSubType(0),
148 _appName(),
149 _appData(NULL),
150 _appLength(0),
151 _xrSendVoIPMetric(false),
edjee@google.com79b02892013-04-04 19:43:34 +0000152 _xrVoIPMetric(),
153 _nackCount(0),
154 _pliCount(0),
155 _fullIntraRequestCount(0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000156{
157 memset(_CNAME, 0, sizeof(_CNAME));
158 memset(_lastSendReport, 0, sizeof(_lastSendReport));
159 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
160
161 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
162}
163
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000164RTCPSender::~RTCPSender() {
165 delete [] _rembSSRC;
166 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000167
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000168 while (!internal_report_blocks_.empty()) {
169 delete internal_report_blocks_.begin()->second;
170 internal_report_blocks_.erase(internal_report_blocks_.begin());
171 }
172 while (!external_report_blocks_.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000173 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000174 external_report_blocks_.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000175 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000176 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000177 }
178 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000179 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000180 _csrcCNAMEs.begin();
181 delete it->second;
182 _csrcCNAMEs.erase(it);
183 }
184 delete _criticalSectionTransport;
185 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000186
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000187 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000188}
189
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000190int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000191RTCPSender::Init()
192{
193 CriticalSectionScoped lock(_criticalSectionRTCPSender);
194
195 _method = kRtcpOff;
196 _cbTransport = NULL;
197 _usingNack = false;
198 _sending = false;
199 _sendTMMBN = false;
200 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000201 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000202 _REMB = false;
203 _sendREMB = false;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000204 last_rtp_timestamp_ = 0;
205 last_frame_capture_time_ms_ = -1;
206 start_timestamp_ = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000207 _SSRC = 0;
208 _remoteSSRC = 0;
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000209 _cameraDelayMS = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000210 _sequenceNumberFIR = 0;
211 _tmmbr_Send = 0;
212 _packetOH_Send = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000213 _nextTimeToSendRTCP = 0;
214 _CSRCs = 0;
215 _appSend = false;
216 _appSubType = 0;
217
218 if(_appData)
219 {
220 delete [] _appData;
221 _appData = NULL;
222 }
223 _appLength = 0;
224
225 _xrSendVoIPMetric = false;
226
227 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
228 memset(_CNAME, 0, sizeof(_CNAME));
229 memset(_lastSendReport, 0, sizeof(_lastSendReport));
230 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
edjee@google.com79b02892013-04-04 19:43:34 +0000231
232 _nackCount = 0;
233 _pliCount = 0;
234 _fullIntraRequestCount = 0;
235
niklase@google.com470e71d2011-07-07 08:21:25 +0000236 return 0;
237}
238
239void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000240RTCPSender::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +0000241{
242 _id = id;
243}
244
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000245int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000246RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
247{
248 CriticalSectionScoped lock(_criticalSectionTransport);
249 _cbTransport = outgoingTransport;
250 return 0;
251}
252
253RTCPMethod
254RTCPSender::Status() const
255{
256 CriticalSectionScoped lock(_criticalSectionRTCPSender);
257 return _method;
258}
259
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000260int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000261RTCPSender::SetRTCPStatus(const RTCPMethod method)
262{
263 CriticalSectionScoped lock(_criticalSectionRTCPSender);
264 if(method != kRtcpOff)
265 {
266 if(_audio)
267 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000268 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000269 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000270 } else
271 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000272 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000273 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000274 }
275 }
276 _method = method;
277 return 0;
278}
279
280bool
281RTCPSender::Sending() const
282{
283 CriticalSectionScoped lock(_criticalSectionRTCPSender);
284 return _sending;
285}
286
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000287int32_t
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000288RTCPSender::SetSendingStatus(const FeedbackState& feedback_state, bool sending)
niklase@google.com470e71d2011-07-07 08:21:25 +0000289{
290 bool sendRTCPBye = false;
291 {
292 CriticalSectionScoped lock(_criticalSectionRTCPSender);
293
294 if(_method != kRtcpOff)
295 {
296 if(sending == false && _sending == true)
297 {
298 // Trigger RTCP bye
299 sendRTCPBye = true;
300 }
301 }
302 _sending = sending;
303 }
304 if(sendRTCPBye)
305 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000306 return SendRTCP(feedback_state, kRtcpBye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000307 }
308 return 0;
309}
310
311bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000312RTCPSender::REMB() const
313{
314 CriticalSectionScoped lock(_criticalSectionRTCPSender);
315 return _REMB;
316}
317
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000318int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000319RTCPSender::SetREMBStatus(const bool enable)
320{
321 CriticalSectionScoped lock(_criticalSectionRTCPSender);
322 _REMB = enable;
323 return 0;
324}
325
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000326int32_t
327RTCPSender::SetREMBData(const uint32_t bitrate,
328 const uint8_t numberOfSSRC,
329 const uint32_t* SSRC)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000330{
331 CriticalSectionScoped lock(_criticalSectionRTCPSender);
332 _rembBitrate = bitrate;
333
334 if(_sizeRembSSRC < numberOfSSRC)
335 {
336 delete [] _rembSSRC;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000337 _rembSSRC = new uint32_t[numberOfSSRC];
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000338 _sizeRembSSRC = numberOfSSRC;
339 }
340
341 _lengthRembSSRC = numberOfSSRC;
342 for (int i = 0; i < numberOfSSRC; i++)
343 {
344 _rembSSRC[i] = SSRC[i];
345 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000346 _sendREMB = true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000347 return 0;
348}
349
350bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000351RTCPSender::TMMBR() const
352{
353 CriticalSectionScoped lock(_criticalSectionRTCPSender);
354 return _TMMBR;
355}
356
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000357int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000358RTCPSender::SetTMMBRStatus(const bool enable)
359{
360 CriticalSectionScoped lock(_criticalSectionRTCPSender);
361 _TMMBR = enable;
362 return 0;
363}
364
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000365bool
366RTCPSender::IJ() const
367{
368 CriticalSectionScoped lock(_criticalSectionRTCPSender);
369 return _IJ;
370}
371
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000372int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000373RTCPSender::SetIJStatus(const bool enable)
374{
375 CriticalSectionScoped lock(_criticalSectionRTCPSender);
376 _IJ = enable;
377 return 0;
378}
379
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000380void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
381 start_timestamp_ = start_timestamp;
382}
383
384void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
385 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000386 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000387 last_rtp_timestamp_ = rtp_timestamp;
388 if (capture_time_ms < 0) {
389 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000390 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000391 } else {
392 last_frame_capture_time_ms_ = capture_time_ms;
393 }
394}
395
niklase@google.com470e71d2011-07-07 08:21:25 +0000396void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000397RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000398{
399 CriticalSectionScoped lock(_criticalSectionRTCPSender);
400
401 if(_SSRC != 0)
402 {
403 // not first SetSSRC, probably due to a collision
404 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000405 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000406 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000407 }
408 _SSRC = ssrc;
409}
410
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000411void RTCPSender::SetRemoteSSRC(uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000412{
413 CriticalSectionScoped lock(_criticalSectionRTCPSender);
414 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000415}
416
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000417int32_t
418RTCPSender::SetCameraDelay(const int32_t delayMS)
419{
420 CriticalSectionScoped lock(_criticalSectionRTCPSender);
421 if(delayMS > 1000 || delayMS < -1000)
422 {
423 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
424 return -1;
425 }
426 _cameraDelayMS = delayMS;
427 return 0;
428}
429
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000430int32_t RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000431 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000432 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000433 cName[RTCP_CNAME_SIZE - 1] = 0;
434 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000435 return 0;
436}
437
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000438int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000439 if (!cName)
440 return -1;
441
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000442 CriticalSectionScoped lock(_criticalSectionRTCPSender);
443 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
444 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
445 return 0;
446}
447
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000448int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
449 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000450 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000451 CriticalSectionScoped lock(_criticalSectionRTCPSender);
452 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
453 return -1;
454 }
455 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000456 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
457 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000458 _csrcCNAMEs[SSRC] = ptr;
459 return 0;
460}
461
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000462int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000463 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000464 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000465 _csrcCNAMEs.find(SSRC);
466
467 if (it == _csrcCNAMEs.end()) {
468 return -1;
469 }
470 delete it->second;
471 _csrcCNAMEs.erase(it);
472 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000473}
474
475bool
476RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
477{
478/*
479 For audio we use a fix 5 sec interval
480
481 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
482 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
483
484
485From RFC 3550
486
487 MAX RTCP BW is 5% if the session BW
488 A send report is approximately 65 bytes inc CNAME
489 A report report is approximately 28 bytes
490
491 The RECOMMENDED value for the reduced minimum in seconds is 360
492 divided by the session bandwidth in kilobits/second. This minimum
493 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
494
495 If the participant has not yet sent an RTCP packet (the variable
496 initial is true), the constant Tmin is set to 2.5 seconds, else it
497 is set to 5 seconds.
498
499 The interval between RTCP packets is varied randomly over the
500 range [0.5,1.5] times the calculated interval to avoid unintended
501 synchronization of all participants
502
503 if we send
504 If the participant is a sender (we_sent true), the constant C is
505 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
506 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
507 number of senders.
508
509 if we receive only
510 If we_sent is not true, the constant C is set
511 to the average RTCP packet size divided by 75% of the RTCP
512 bandwidth. The constant n is set to the number of receivers
513 (members - senders). If the number of senders is greater than
514 25%, senders and receivers are treated together.
515
516 reconsideration NOT required for peer-to-peer
517 "timer reconsideration" is
518 employed. This algorithm implements a simple back-off mechanism
519 which causes users to hold back RTCP packet transmission if the
520 group sizes are increasing.
521
522 n = number of members
523 C = avg_size/(rtcpBW/4)
524
525 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
526
527 4. The calculated interval T is set to a number uniformly distributed
528 between 0.5 and 1.5 times the deterministic calculated interval.
529
530 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
531 for the fact that the timer reconsideration algorithm converges to
532 a value of the RTCP bandwidth below the intended average
533*/
534
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000535 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000536
537 CriticalSectionScoped lock(_criticalSectionRTCPSender);
538
niklase@google.com470e71d2011-07-07 08:21:25 +0000539 if(_method == kRtcpOff)
540 {
541 return false;
542 }
543
niklase@google.com470e71d2011-07-07 08:21:25 +0000544 if(!_audio && sendKeyframeBeforeRTP)
545 {
546 // for video key-frames we want to send the RTCP before the large key-frame
547 // if we have a 100 ms margin
548 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
549 }
550
551 if(now > _nextTimeToSendRTCP)
552 {
553 return true;
554
555 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
556 {
557 // wrap
558 return true;
559 }
560 return false;
561}
562
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000563uint32_t
564RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000565{
566 CriticalSectionScoped lock(_criticalSectionRTCPSender);
567
568 lastRTCPTime = _lastRTCPTime[0];
569 return _lastSendReport[0];
570}
571
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000572uint32_t
573RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000574{
575 CriticalSectionScoped lock(_criticalSectionRTCPSender);
576
577 // This is only saved when we are the sender
578 if((_lastSendReport[0] == 0) || (sendReport == 0))
579 {
580 return 0; // will be ignored
581 } else
582 {
583 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
584 {
585 if( _lastSendReport[i] == sendReport)
586 {
587 return _lastRTCPTime[i];
588 }
589 }
590 }
591 return 0;
592}
593
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000594int32_t RTCPSender::AddExternalReportBlock(
595 uint32_t SSRC,
596 const RTCPReportBlock* reportBlock) {
597 CriticalSectionScoped lock(_criticalSectionRTCPSender);
598 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
599}
600
601int32_t RTCPSender::AddReportBlock(
602 uint32_t SSRC,
603 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
604 const RTCPReportBlock* reportBlock) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000605 if (reportBlock == NULL) {
606 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
607 "%s invalid argument", __FUNCTION__);
608 return -1;
609 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000610
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000611 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000612 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
613 "%s invalid argument", __FUNCTION__);
614 return -1;
615 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000616 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000617 report_blocks->find(SSRC);
618 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000619 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000620 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000621 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000622 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
623 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000624 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000625 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000626}
627
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000628int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000629 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000630
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000631 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000632 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000633
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000634 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000635 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000636 }
637 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000638 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000639 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000640}
641
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000642int32_t RTCPSender::BuildSR(const FeedbackState& feedback_state,
643 uint8_t* rtcpbuffer,
644 int& pos,
645 uint32_t NTPsec,
646 uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000647{
648 // sanity
649 if(pos + 52 >= IP_PACKET_SIZE)
650 {
651 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
652 return -2;
653 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000654 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000655
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000656 uint32_t posNumberOfReportBlocks = pos;
657 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000658
659 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000660 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000661
662 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
663 {
664 // shift old
665 _lastSendReport[i+1] = _lastSendReport[i];
666 _lastRTCPTime[i+1] =_lastRTCPTime[i];
667 }
668
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000669 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000670 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000671
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000672 // The timestamp of this RTCP packet should be estimated as the timestamp of
673 // the frame being captured at this moment. We are calculating that
674 // timestamp as the last frame's timestamp + the time since the last frame
675 // was captured.
676 {
677 // Needs protection since this method is called on the process thread.
678 CriticalSectionScoped lock(_criticalSectionRTCPSender);
679 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
680 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000681 (feedback_state.frequency_hz / 1000);
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000682 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000683
684 // Add sender data
685 // Save for our length field
686 pos++;
687 pos++;
688
689 // Add our own SSRC
690 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
691 pos += 4;
692 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000693 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000694 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000695 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000696 pos += 4;
697 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
698 pos += 4;
699
700 //sender's packet count
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000701 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
702 feedback_state.packet_count_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000703 pos += 4;
704
705 //sender's octet count
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000706 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
707 feedback_state.byte_count_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000708 pos += 4;
709
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000710 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000711 int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
712 numberOfReportBlocks,
713 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000714 if(retVal < 0)
715 {
716 //
717 return retVal ;
718 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000719 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000720 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
721
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000722 uint16_t len = uint16_t((pos/4) -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000723 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
724 return 0;
725}
726
727
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000728int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000729 size_t lengthCname = strlen(_CNAME);
730 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000731
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000732 // sanity
733 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
734 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
735 "%s invalid argument", __FUNCTION__);
736 return -2;
737 }
738 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000739
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000740 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000741 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
742 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000743
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000744 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000745 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000746 pos++;
747 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000748
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000749 // Add our own SSRC
750 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
751 pos += 4;
752
753 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000754 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000755
756 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000757 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000758
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000759 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000760
761 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
762 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000763 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000764
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000765 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000766 // We must have a zero field even if we have an even multiple of 4 bytes
767 if ((pos % 4) == 0) {
768 padding++;
769 rtcpbuffer[pos++]=0;
770 }
771 while ((pos % 4) != 0) {
772 padding++;
773 rtcpbuffer[pos++]=0;
774 }
775 SDESLength += padding;
776
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000777 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000778 _csrcCNAMEs.begin();
779
780 for(; it != _csrcCNAMEs.end(); it++) {
781 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000782 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000783
784 // Add SSRC
785 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000786 pos += 4;
787
788 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000789 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000790
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000791 size_t length = strlen(cname->name);
792 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000793
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000794 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000795 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000796
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000797 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000798
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000799 pos += length;
800 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000801 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000802
803 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000804 if((pos % 4) == 0){
805 padding++;
806 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000807 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000808 while((pos % 4) != 0){
809 padding++;
810 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000811 }
812 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000813 }
814 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000815 uint16_t buffer_length = (SDESLength / 4) - 1;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000816 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
817 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000818 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000819}
820
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000821int32_t
822RTCPSender::BuildRR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000823 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000824 const uint32_t NTPsec,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000825 const uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000826{
827 // sanity one block
828 if(pos + 32 >= IP_PACKET_SIZE)
829 {
830 return -2;
831 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000832 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000833
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000834 rtcpbuffer[pos++]=(uint8_t)0x80;
835 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000836
837 // Save for our length field
838 pos++;
839 pos++;
840
841 // Add our own SSRC
842 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
843 pos += 4;
844
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000845 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000846 int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
847 numberOfReportBlocks,
848 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000849 if(retVal < 0)
850 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000851 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000852 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000853 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000854 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
855
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000856 uint16_t len = uint16_t((pos)/4 -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000857 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
858 return 0;
859}
860
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000861// From RFC 5450: Transmission Time Offsets in RTP Streams.
862// 0 1 2 3
863// 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
864// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
865// hdr |V=2|P| RC | PT=IJ=195 | length |
866// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
867// | inter-arrival jitter |
868// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
869// . .
870// . .
871// . .
872// | inter-arrival jitter |
873// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
874//
875// If present, this RTCP packet must be placed after a receiver report
876// (inside a compound RTCP packet), and MUST have the same value for RC
877// (reception report count) as the receiver report.
878
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000879int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000880RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000881 uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000882 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000883 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000884{
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000885 if (external_report_blocks_.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000886 {
887 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
888 return 0;
889 }
890
891 // sanity
892 if(pos + 8 >= IP_PACKET_SIZE)
893 {
894 return -2;
895 }
896 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000897 uint8_t RC = 1;
898 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
899 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000900
901 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000902 rtcpbuffer[pos++]=(uint8_t)0;
903 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000904
905 // Add inter-arrival jitter
906 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
907 jitterTransmissionTimeOffset);
908 pos += 4;
909 return 0;
910}
911
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000912int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000913RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000914{
915 // sanity
916 if(pos + 12 >= IP_PACKET_SIZE)
917 {
918 return -2;
919 }
920 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000921 uint8_t FMT = 1;
922 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
923 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000924
925 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000926 rtcpbuffer[pos++]=(uint8_t)0;
927 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000928
929 // Add our own SSRC
930 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
931 pos += 4;
932
933 // Add the remote SSRC
934 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
935 pos += 4;
936 return 0;
937}
938
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000939int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000940 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000941 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000942 // sanity
943 if(pos + 20 >= IP_PACKET_SIZE) {
944 return -2;
945 }
946 if (!repeat) {
947 _sequenceNumberFIR++; // do not increase if repetition
948 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000949
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000950 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000951 uint8_t FMT = 4;
952 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
953 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000954
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000955 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000956 rtcpbuffer[pos++] = (uint8_t)0;
957 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000958
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000959 // Add our own SSRC
960 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
961 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000962
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000963 // RFC 5104 4.3.1.2. Semantics
964 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000965 rtcpbuffer[pos++] = (uint8_t)0;
966 rtcpbuffer[pos++] = (uint8_t)0;
967 rtcpbuffer[pos++] = (uint8_t)0;
968 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000969
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000970 // Additional Feedback Control Information (FCI)
971 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
972 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000973
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000974 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
975 rtcpbuffer[pos++] = (uint8_t)0;
976 rtcpbuffer[pos++] = (uint8_t)0;
977 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000978 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000979}
980
981/*
982 0 1 2 3
983 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
984 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
985 | First | Number | PictureID |
986 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
987*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000988int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000989RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000990{
991 // sanity
992 if(pos + 16 >= IP_PACKET_SIZE)
993 {
994 return -2;
995 }
996 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000997 uint8_t FMT = 2;
998 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
999 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001000
1001 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001002 rtcpbuffer[pos++]=(uint8_t)0;
1003 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +00001004
1005 // Add our own SSRC
1006 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1007 pos += 4;
1008
1009 // Add the remote SSRC
1010 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1011 pos += 4;
1012
1013 // Add first, number & picture ID 6 bits
1014 // first = 0, 13 - bits
1015 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001016 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +00001017 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
1018 pos += 4;
1019 return 0;
1020}
1021
1022/*
1023 0 1 2 3
1024 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
1025 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1026 | PB |0| Payload Type| Native RPSI bit string |
1027 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1028 | defined per codec ... | Padding (0) |
1029 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1030*/
1031/*
1032* Note: not generic made for VP8
1033*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001034int32_t
1035RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001036 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001037 const uint64_t pictureID,
1038 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +00001039{
1040 // sanity
1041 if(pos + 24 >= IP_PACKET_SIZE)
1042 {
1043 return -2;
1044 }
1045 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001046 uint8_t FMT = 3;
1047 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1048 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001049
1050 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001051 uint32_t bitsRequired = 7;
1052 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001053 while((pictureID>>bitsRequired) > 0)
1054 {
1055 bitsRequired += 7;
1056 bytesRequired++;
1057 }
1058
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001059 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001060 if(bytesRequired > 6)
1061 {
1062 size = 5;
1063 } else if(bytesRequired > 2)
1064 {
1065 size = 4;
1066 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001067 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001068 rtcpbuffer[pos++]=size;
1069
1070 // Add our own SSRC
1071 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1072 pos += 4;
1073
1074 // Add the remote SSRC
1075 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1076 pos += 4;
1077
1078 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001079 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001080 if(paddingBytes == 4)
1081 {
1082 paddingBytes = 0;
1083 }
1084 // add padding length in bits
1085 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1086 pos++;
1087
1088 // add payload type
1089 rtcpbuffer[pos] = payloadType;
1090 pos++;
1091
1092 // add picture ID
1093 for(int i = bytesRequired-1; i > 0; i--)
1094 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001095 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001096 pos++;
1097 }
1098 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001099 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001100 pos++;
1101
1102 // add padding
1103 for(int j = 0; j <paddingBytes; j++)
1104 {
1105 rtcpbuffer[pos] = 0;
1106 pos++;
1107 }
1108 return 0;
1109}
1110
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001111int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001112RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001113{
1114 // sanity
1115 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1116 {
1117 return -2;
1118 }
1119 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001120 uint8_t FMT = 15;
1121 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1122 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001123
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001124 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001125 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1126
1127 // Add our own SSRC
1128 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1129 pos += 4;
1130
1131 // Remote SSRC must be 0
1132 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1133 pos += 4;
1134
1135 rtcpbuffer[pos++]='R';
1136 rtcpbuffer[pos++]='E';
1137 rtcpbuffer[pos++]='M';
1138 rtcpbuffer[pos++]='B';
1139
1140 rtcpbuffer[pos++] = _lengthRembSSRC;
1141 // 6 bit Exp
1142 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001143 uint8_t brExp = 0;
1144 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001145 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001146 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001147 {
1148 brExp = i;
1149 break;
1150 }
1151 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001152 const uint32_t brMantissa = (_rembBitrate >> brExp);
1153 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1154 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1155 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001156
1157 for (int i = 0; i < _lengthRembSSRC; i++)
1158 {
1159 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1160 pos += 4;
1161 }
1162 return 0;
1163}
1164
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001165void
1166RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001167{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001168 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001169 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001170}
1171
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001172int32_t RTCPSender::BuildTMMBR(ModuleRtpRtcpImpl* rtp_rtcp_module,
1173 uint8_t* rtcpbuffer,
1174 int& pos) {
1175 if (rtp_rtcp_module == NULL)
1176 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001177 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1178 // If the sender is an owner of the TMMBN -> send TMMBR
1179 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1180
niklase@google.com470e71d2011-07-07 08:21:25 +00001181 // get current bounding set from RTCP receiver
1182 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001183 // store in candidateSet, allocates one extra slot
1184 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001185
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001186 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1187 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1188 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001189 int32_t lengthOfBoundingSet =
1190 rtp_rtcp_module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001191
1192 if(lengthOfBoundingSet > 0)
1193 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001194 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001195 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001196 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1197 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001198 {
1199 // do not send the same tuple
1200 return 0;
1201 }
1202 }
1203 if(!tmmbrOwner)
1204 {
1205 // use received bounding set as candidate set
1206 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001207 candidateSet->SetEntry(lengthOfBoundingSet,
1208 _tmmbr_Send,
1209 _packetOH_Send,
1210 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001211 int numCandidates = lengthOfBoundingSet+ 1;
1212
1213 // find bounding set
1214 TMMBRSet* boundingSet = NULL;
1215 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1216 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1217 {
1218 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1219 }
1220 if(!tmmbrOwner)
1221 {
1222 // did not enter bounding set, no meaning to send this request
1223 return 0;
1224 }
1225 }
1226 }
1227
1228 if(_tmmbr_Send)
1229 {
1230 // sanity
1231 if(pos + 20 >= IP_PACKET_SIZE)
1232 {
1233 return -2;
1234 }
1235 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001236 uint8_t FMT = 3;
1237 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1238 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001239
1240 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001241 rtcpbuffer[pos++]=(uint8_t)0;
1242 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001243
1244 // Add our own SSRC
1245 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1246 pos += 4;
1247
1248 // RFC 5104 4.2.1.2. Semantics
1249
1250 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001251 rtcpbuffer[pos++]=(uint8_t)0;
1252 rtcpbuffer[pos++]=(uint8_t)0;
1253 rtcpbuffer[pos++]=(uint8_t)0;
1254 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001255
1256 // Additional Feedback Control Information (FCI)
1257 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1258 pos += 4;
1259
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001260 uint32_t bitRate = _tmmbr_Send*1000;
1261 uint32_t mmbrExp = 0;
1262 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001263 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001264 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001265 {
1266 mmbrExp = i;
1267 break;
1268 }
1269 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001270 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001271
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001272 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1273 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1274 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1275 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001276 }
1277 return 0;
1278}
1279
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001280int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001281RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001282{
1283 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1284 if(boundingSet == NULL)
1285 {
1286 return -1;
1287 }
1288 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001289 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001290 {
1291 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1292 return -2;
1293 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001294 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001295 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001296 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1297 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001298
1299 //Add length later
1300 int posLength = pos;
1301 pos++;
1302 pos++;
1303
1304 // Add our own SSRC
1305 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1306 pos += 4;
1307
1308 // RFC 5104 4.2.2.2. Semantics
1309
1310 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001311 rtcpbuffer[pos++]=(uint8_t)0;
1312 rtcpbuffer[pos++]=(uint8_t)0;
1313 rtcpbuffer[pos++]=(uint8_t)0;
1314 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001315
1316 // Additional Feedback Control Information (FCI)
1317 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001318 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001319 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001320 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001321 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001322 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001323 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1324 pos += 4;
1325
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001326 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1327 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001328 for(int i=0; i<64; i++)
1329 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001330 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001331 {
1332 mmbrExp = i;
1333 break;
1334 }
1335 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001336 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1337 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001338
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001339 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1340 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1341 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1342 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001343 numBoundingSet++;
1344 }
1345 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001346 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1347 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1348 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001349 return 0;
1350}
1351
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001352int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001353RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001354{
1355 // sanity
1356 if(_appData == NULL)
1357 {
1358 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1359 return -1;
1360 }
1361 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1362 {
1363 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1364 return -2;
1365 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001366 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001367
1368 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001369 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001370
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001371 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1372 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1373 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001374
1375 // Add our own SSRC
1376 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1377 pos += 4;
1378
1379 // Add our application name
1380 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1381 pos += 4;
1382
1383 // Add the data
1384 memcpy(rtcpbuffer +pos, _appData,_appLength);
1385 pos += _appLength;
1386 return 0;
1387}
1388
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001389int32_t
1390RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001391 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001392 const int32_t nackSize,
1393 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001394 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001395{
1396 // sanity
1397 if(pos + 16 >= IP_PACKET_SIZE)
1398 {
1399 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1400 return -2;
1401 }
1402
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001403 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001404 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001405 uint8_t FMT = 1;
1406 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1407 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001408
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001409 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001410 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001411 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001412
1413 // Add our own SSRC
1414 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1415 pos += 4;
1416
1417 // Add the remote SSRC
1418 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1419 pos += 4;
1420
edjee@google.com79b02892013-04-04 19:43:34 +00001421 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001422 // Build NACK bitmasks and write them to the RTCP message.
1423 // The nack list should be sorted and not contain duplicates if one
1424 // wants to build the smallest rtcp nack packet.
1425 int numOfNackFields = 0;
1426 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1427 (IP_PACKET_SIZE - pos) / 4);
1428 int i = 0;
1429 while (i < nackSize && numOfNackFields < maxNackFields) {
1430 stringBuilder.PushNACK(nackList[i]);
1431 uint16_t nack = nackList[i++];
1432 uint16_t bitmask = 0;
1433 while (i < nackSize) {
1434 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1435 if (shift >= 0 && shift <= 15) {
1436 stringBuilder.PushNACK(nackList[i]);
1437 bitmask |= (1 << shift);
1438 ++i;
1439 } else {
1440 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001441 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001442 }
1443 // Write the sequence number and the bitmask to the packet.
1444 assert(pos + 4 < IP_PACKET_SIZE);
1445 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
1446 pos += 2;
1447 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
1448 pos += 2;
1449 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001450 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001451 if (i != nackSize) {
1452 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1453 "Nack list to large for one packet.");
1454 }
1455 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001456 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001457 return 0;
1458}
1459
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001460int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001461RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001462{
1463 // sanity
1464 if(pos + 8 >= IP_PACKET_SIZE)
1465 {
1466 return -2;
1467 }
1468 if(_includeCSRCs)
1469 {
1470 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001471 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1472 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001473
1474 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001475 rtcpbuffer[pos++]=(uint8_t)0;
1476 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001477
1478 // Add our own SSRC
1479 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1480 pos += 4;
1481
1482 // add CSRCs
1483 for(int i = 0; i < _CSRCs; i++)
1484 {
1485 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1486 pos += 4;
1487 }
1488 } else
1489 {
1490 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001491 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1492 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001493
1494 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001495 rtcpbuffer[pos++]=(uint8_t)0;
1496 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001497
1498 // Add our own SSRC
1499 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1500 pos += 4;
1501 }
1502 return 0;
1503}
1504
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001505int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001506RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001507{
1508 // sanity
1509 if(pos + 44 >= IP_PACKET_SIZE)
1510 {
1511 return -2;
1512 }
1513
1514 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001515 rtcpbuffer[pos++]=(uint8_t)0x80;
1516 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001517
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001518 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001519
1520 // handle length later on
1521 pos++;
1522 pos++;
1523
1524 // Add our own SSRC
1525 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1526 pos += 4;
1527
1528 // Add a VoIP metrics block
1529 rtcpbuffer[pos++]=7;
1530 rtcpbuffer[pos++]=0;
1531 rtcpbuffer[pos++]=0;
1532 rtcpbuffer[pos++]=8;
1533
1534 // Add the remote SSRC
1535 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1536 pos += 4;
1537
1538 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1539 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1540 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1541 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1542
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001543 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1544 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1545 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1546 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001547
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001548 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1549 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1550 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1551 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001552
1553 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1554 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1555 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1556 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1557
1558 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1559 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1560 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1561 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1562
1563 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1564 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001565 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1566 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001567
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001568 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1569 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1570 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1571 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001572
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001573 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1574 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001575 return 0;
1576}
1577
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001578int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
1579 uint32_t packetTypeFlags,
1580 int32_t nackSize,
1581 const uint16_t* nackList,
1582 bool repeat,
1583 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001584 {
1585 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1586 if(_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001587 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001588 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1589 "%s invalid state", __FUNCTION__);
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001590 return -1;
1591 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001592 }
1593 uint8_t rtcp_buffer[IP_PACKET_SIZE];
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001594 int rtcp_length = PrepareRTCP(feedback_state,
1595 packetTypeFlags,
1596 nackSize,
1597 nackList,
1598 repeat,
1599 pictureID,
1600 rtcp_buffer,
1601 IP_PACKET_SIZE);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001602 if (rtcp_length < 0) {
1603 return -1;
1604 }
1605 // Sanity don't send empty packets.
1606 if (rtcp_length == 0)
1607 {
1608 return -1;
1609 }
1610 return SendToNetwork(rtcp_buffer, static_cast<uint16_t>(rtcp_length));
1611}
1612
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001613int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
1614 uint32_t packetTypeFlags,
1615 int32_t nackSize,
1616 const uint16_t* nackList,
1617 bool repeat,
1618 uint64_t pictureID,
1619 uint8_t* rtcp_buffer,
1620 int buffer_size) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001621 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1622 // Collect the received information.
1623 uint32_t NTPsec = 0;
1624 uint32_t NTPfrac = 0;
1625 uint32_t jitterTransmissionOffset = 0;
1626 int position = 0;
1627
1628 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1629
1630 if(_TMMBR ) // Attach TMMBR to send and receive reports.
1631 {
1632 rtcpPacketTypeFlags |= kRtcpTmmbr;
1633 }
1634 if(_appSend)
1635 {
1636 rtcpPacketTypeFlags |= kRtcpApp;
1637 _appSend = false;
1638 }
1639 if(_REMB && _sendREMB)
1640 {
1641 // Always attach REMB to SR if that is configured. Note that REMB is
1642 // only sent on one of the RTP modules in the REMB group.
1643 rtcpPacketTypeFlags |= kRtcpRemb;
1644 }
1645 if(_xrSendVoIPMetric)
1646 {
1647 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1648 _xrSendVoIPMetric = false;
1649 }
1650 if(_sendTMMBN) // Set when having received a TMMBR.
1651 {
1652 rtcpPacketTypeFlags |= kRtcpTmmbn;
1653 _sendTMMBN = false;
1654 }
1655
1656 if(_method == kRtcpCompound)
1657 {
1658 if(_sending)
1659 {
1660 rtcpPacketTypeFlags |= kRtcpSr;
1661 } else
1662 {
1663 rtcpPacketTypeFlags |= kRtcpRr;
1664 }
1665 } else if(_method == kRtcpNonCompound)
1666 {
1667 if(rtcpPacketTypeFlags & kRtcpReport)
1668 {
1669 if(_sending)
1670 {
1671 rtcpPacketTypeFlags |= kRtcpSr;
1672 } else
1673 {
1674 rtcpPacketTypeFlags |= kRtcpRr;
1675 }
1676 }
1677 }
1678 if( rtcpPacketTypeFlags & kRtcpRr ||
1679 rtcpPacketTypeFlags & kRtcpSr)
1680 {
1681 // generate next time to send a RTCP report
1682 // seeded from RTP constructor
1683 int32_t random = rand() % 1000;
1684 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1685
1686 if(_audio)
1687 {
1688 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1689 (RTCP_INTERVAL_AUDIO_MS*random/1000);
1690 }else
1691 {
1692 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1693 if(_sending)
1694 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001695 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1696 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1697 if (send_bitrate_kbit != 0)
1698 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001699 }
1700 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1701 {
1702 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1703 }
1704 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1705 }
1706 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1707 }
1708
1709 // If the data does not fit in the packet we fill it as much as possible.
1710 int32_t buildVal = 0;
1711
1712 // We need to send our NTP even if we haven't received any reports.
1713 _clock->CurrentNtp(NTPsec, NTPfrac);
1714 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1715 StatisticianMap statisticians =
1716 receive_statistics_->GetActiveStatisticians();
1717 if (!statisticians.empty()) {
1718 StatisticianMap::const_iterator it;
1719 int i;
1720 for (it = statisticians.begin(), i = 0; it != statisticians.end();
1721 ++it, ++i) {
1722 RTCPReportBlock report_block;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001723 if (PrepareReport(
1724 feedback_state, it->second, &report_block, &NTPsec, &NTPfrac))
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001725 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1726 }
1727 if (_IJ && !statisticians.empty()) {
1728 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1729 }
1730 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
1731 }
1732 }
1733
1734 if(rtcpPacketTypeFlags & kRtcpSr)
1735 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001736 buildVal = BuildSR(feedback_state, rtcp_buffer, position, NTPsec, NTPfrac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001737 if (buildVal == -1) {
1738 return -1;
1739 } else if (buildVal == -2) {
1740 return position;
1741 }
1742 buildVal = BuildSDEC(rtcp_buffer, position);
1743 if (buildVal == -1) {
1744 return -1;
1745 } else if (buildVal == -2) {
1746 return position;
1747 }
1748 }else if(rtcpPacketTypeFlags & kRtcpRr)
1749 {
1750 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1751 if (buildVal == -1) {
1752 return -1;
1753 } else if (buildVal == -2) {
1754 return position;
1755 }
1756 // only of set
1757 if(_CNAME[0] != 0)
1758 {
1759 buildVal = BuildSDEC(rtcp_buffer, position);
1760 if (buildVal == -1) {
1761 return -1;
1762 }
1763 }
1764 }
1765 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1766 {
1767 // If present, this RTCP packet must be placed after a
1768 // receiver report.
1769 buildVal = BuildExtendedJitterReport(rtcp_buffer,
1770 position,
1771 jitterTransmissionOffset);
1772 if (buildVal == -1) {
1773 return -1;
1774 } else if (buildVal == -2) {
1775 return position;
1776 }
1777 }
1778 if(rtcpPacketTypeFlags & kRtcpPli)
1779 {
1780 buildVal = BuildPLI(rtcp_buffer, position);
1781 if (buildVal == -1) {
1782 return -1;
1783 } else if (buildVal == -2) {
1784 return position;
1785 }
1786 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
1787 _pliCount++;
1788 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC, _pliCount);
1789 }
1790 if(rtcpPacketTypeFlags & kRtcpFir)
1791 {
1792 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1793 if (buildVal == -1) {
1794 return -1;
1795 } else if (buildVal == -2) {
1796 return position;
1797 }
1798 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
1799 _fullIntraRequestCount++;
1800 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
1801 _fullIntraRequestCount);
1802 }
1803 if(rtcpPacketTypeFlags & kRtcpSli)
1804 {
1805 buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1806 if (buildVal == -1) {
1807 return -1;
1808 } else if (buildVal == -2) {
1809 return position;
1810 }
1811 }
1812 if(rtcpPacketTypeFlags & kRtcpRpsi)
1813 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001814 const int8_t payloadType = feedback_state.send_payload_type;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001815 if (payloadType == -1) {
1816 return -1;
1817 }
1818 buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1819 (uint8_t)payloadType);
1820 if (buildVal == -1) {
1821 return -1;
1822 } else if (buildVal == -2) {
1823 return position;
1824 }
1825 }
1826 if(rtcpPacketTypeFlags & kRtcpRemb)
1827 {
1828 buildVal = BuildREMB(rtcp_buffer, position);
1829 if (buildVal == -1) {
1830 return -1;
1831 } else if (buildVal == -2) {
1832 return position;
1833 }
1834 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1835 }
1836 if(rtcpPacketTypeFlags & kRtcpBye)
1837 {
1838 buildVal = BuildBYE(rtcp_buffer, position);
1839 if (buildVal == -1) {
1840 return -1;
1841 } else if (buildVal == -2) {
1842 return position;
1843 }
1844 }
1845 if(rtcpPacketTypeFlags & kRtcpApp)
1846 {
1847 buildVal = BuildAPP(rtcp_buffer, position);
1848 if (buildVal == -1) {
1849 return -1;
1850 } else if (buildVal == -2) {
1851 return position;
1852 }
1853 }
1854 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1855 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001856 buildVal = BuildTMMBR(feedback_state.module, rtcp_buffer, position);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001857 if (buildVal == -1) {
1858 return -1;
1859 } else if (buildVal == -2) {
1860 return position;
1861 }
1862 }
1863 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1864 {
1865 buildVal = BuildTMMBN(rtcp_buffer, position);
1866 if (buildVal == -1) {
1867 return -1;
1868 } else if (buildVal == -2) {
1869 return position;
1870 }
1871 }
1872 if(rtcpPacketTypeFlags & kRtcpNack)
1873 {
1874 std::string nackString;
1875 buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
1876 &nackString);
1877 if (buildVal == -1) {
1878 return -1;
1879 } else if (buildVal == -2) {
1880 return position;
1881 }
1882 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
1883 "nacks", TRACE_STR_COPY(nackString.c_str()));
1884 _nackCount++;
1885 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC, _nackCount);
1886 }
1887 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1888 {
1889 buildVal = BuildVoIPMetric(rtcp_buffer, position);
1890 if (buildVal == -1) {
1891 return -1;
1892 } else if (buildVal == -2) {
1893 return position;
1894 }
1895 }
1896 return position;
1897}
1898
1899bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
1900 return Status() == kRtcpCompound ||
1901 (rtcp_packet_type & kRtcpReport) ||
1902 (rtcp_packet_type & kRtcpSr) ||
1903 (rtcp_packet_type & kRtcpRr);
1904}
1905
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001906bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
1907 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001908 RTCPReportBlock* report_block,
1909 uint32_t* ntp_secs, uint32_t* ntp_frac) {
1910 // Do we have receive statistics to send?
1911 StreamStatistician::Statistics stats;
1912 if (!statistician->GetStatistics(&stats, true))
1913 return false;
1914 report_block->fractionLost = stats.fraction_lost;
1915 report_block->cumulativeLost = stats.cumulative_lost;
1916 report_block->extendedHighSeqNum =
1917 stats.extended_max_sequence_number;
1918 report_block->jitter = stats.jitter;
1919
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001920 // get our NTP as late as possible to avoid a race
1921 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
1922
1923 // Delay since last received report
1924 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001925 if ((feedback_state.last_rr_ntp_secs != 0) ||
1926 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001927 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1928 uint32_t now=*ntp_secs&0x0000FFFF;
1929 now <<=16;
1930 now += (*ntp_frac&0xffff0000)>>16;
1931
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001932 uint32_t receiveTime = feedback_state.last_rr_ntp_secs&0x0000FFFF;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001933 receiveTime <<=16;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001934 receiveTime += (feedback_state.last_rr_ntp_frac&0xffff0000)>>16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001935
1936 delaySinceLastReceivedSR = now-receiveTime;
1937 }
1938 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001939 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001940 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001941}
1942
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001943int32_t
1944RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
1945 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001946{
1947 CriticalSectionScoped lock(_criticalSectionTransport);
1948 if(_cbTransport)
1949 {
1950 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1951 {
1952 return 0;
1953 }
1954 }
1955 return -1;
1956}
1957
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001958int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00001959RTCPSender::SetCSRCStatus(const bool include)
1960{
1961 _includeCSRCs = include;
1962 return 0;
1963}
1964
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001965int32_t
1966RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
1967 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00001968{
1969 if(arrLength > kRtpCsrcSize)
1970 {
1971 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1972 assert(false);
1973 return -1;
1974 }
1975
1976 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1977
1978 for(int i = 0; i < arrLength;i++)
1979 {
1980 _CSRC[i] = arrOfCSRC[i];
1981 }
1982 _CSRCs = arrLength;
1983 return 0;
1984}
1985
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001986int32_t
1987RTCPSender::SetApplicationSpecificData(const uint8_t subType,
1988 const uint32_t name,
1989 const uint8_t* data,
1990 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001991{
1992 if(length %4 != 0)
1993 {
1994 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1995 return -1;
1996 }
1997 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1998
1999 if(_appData)
2000 {
2001 delete [] _appData;
2002 }
2003
2004 _appSend = true;
2005 _appSubType = subType;
2006 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002007 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002008 _appLength = length;
2009 memcpy(_appData, data, length);
2010 return 0;
2011}
2012
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002013int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002014RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2015{
2016 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2017 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2018
2019 _xrSendVoIPMetric = true;
2020 return 0;
2021}
2022
2023// called under critsect _criticalSectionRTCPSender
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002024int32_t RTCPSender::WriteAllReportBlocksToBuffer(
2025 uint8_t* rtcpbuffer,
2026 int pos,
2027 uint8_t& numberOfReportBlocks,
2028 const uint32_t NTPsec,
2029 const uint32_t NTPfrac) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002030 // sanity one block
2031 if(pos + 24 >= IP_PACKET_SIZE) {
2032 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2033 "%s invalid argument", __FUNCTION__);
2034 return -1;
2035 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002036 numberOfReportBlocks = external_report_blocks_.size();
2037 numberOfReportBlocks += internal_report_blocks_.size();
2038 if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002039 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2040 "%s invalid argument", __FUNCTION__);
2041 return -1;
2042 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002043 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2044 while (!internal_report_blocks_.empty()) {
2045 delete internal_report_blocks_.begin()->second;
2046 internal_report_blocks_.erase(internal_report_blocks_.begin());
2047 }
2048 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2049 return pos;
2050}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002051
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002052int32_t RTCPSender::WriteReportBlocksToBuffer(
2053 uint8_t* rtcpbuffer,
2054 int32_t position,
2055 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2056 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2057 report_blocks.begin();
2058 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002059 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002060 RTCPReportBlock* reportBlock = it->second;
2061 if (reportBlock) {
2062 // Remote SSRC
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002063 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position, remoteSSRC);
2064 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002065
2066 // fraction lost
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002067 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002068
2069 // cumulative loss
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002070 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002071 reportBlock->cumulativeLost);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002072 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002073
2074 // extended highest seq_no, contain the highest sequence number received
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002075 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002076 reportBlock->extendedHighSeqNum);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002077 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002078
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002079 // Jitter
2080 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002081 reportBlock->jitter);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002082 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002083
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002084 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002085 reportBlock->lastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002086 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002087
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002088 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002089 reportBlock->delaySinceLastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002090 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002091 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002092 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002093 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00002094}
2095
2096// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002097int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002098RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002099 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002100{
2101 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2102
2103 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2104 {
2105 _sendTMMBN = true;
2106 return 0;
2107 }
2108 return -1;
2109}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002110} // namespace webrtc