blob: b9ab0c1e975f021d708c196a385d1b9935c5dc52 [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"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000022#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000023#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
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000080 has_last_xr_rr = module->LastReceivedXrReferenceTimeInfo(&last_xr_rr);
81
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000082 uint32_t send_bitrate = 0, tmp;
83 module->BitrateSent(&send_bitrate, &tmp, &tmp, &tmp);
84 this->send_bitrate = send_bitrate;
85}
86
87RTCPSender::FeedbackState::FeedbackState()
88 : send_payload_type(0),
89 frequency_hz(0),
90 packet_count_sent(0),
91 byte_count_sent(0),
92 send_bitrate(0),
93 last_rr_ntp_secs(0),
94 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000095 remote_sr(0),
96 has_last_xr_rr(false) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000097
pbos@webrtc.org2f446732013-04-08 11:08:41 +000098RTCPSender::RTCPSender(const int32_t id,
niklase@google.com470e71d2011-07-07 08:21:25 +000099 const bool audio,
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000100 Clock* clock,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000101 ReceiveStatistics* receive_statistics) :
niklase@google.com470e71d2011-07-07 08:21:25 +0000102 _id(id),
103 _audio(audio),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000104 _clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +0000105 _method(kRtcpOff),
henrike@webrtc.org65573f22011-12-13 19:17:27 +0000106 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +0000107 _cbTransport(NULL),
108
henrike@webrtc.org65573f22011-12-13 19:17:27 +0000109 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +0000110 _usingNack(false),
111 _sending(false),
112 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000113 _REMB(false),
114 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000115 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000116 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000117 _nextTimeToSendRTCP(0),
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000118 start_timestamp_(0),
119 last_rtp_timestamp_(0),
120 last_frame_capture_time_ms_(-1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000121 _SSRC(0),
122 _remoteSSRC(0),
123 _CNAME(),
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000124 receive_statistics_(receive_statistics),
125 internal_report_blocks_(),
126 external_report_blocks_(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000127 _csrcCNAMEs(),
128
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000129 _cameraDelayMS(0),
130
niklase@google.com470e71d2011-07-07 08:21:25 +0000131 _lastSendReport(),
132 _lastRTCPTime(),
133
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000134 last_xr_rr_(),
135
niklase@google.com470e71d2011-07-07 08:21:25 +0000136 _CSRCs(0),
137 _CSRC(),
138 _includeCSRCs(true),
139
140 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000141
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000142 _lengthRembSSRC(0),
143 _sizeRembSSRC(0),
144 _rembSSRC(NULL),
145 _rembBitrate(0),
146
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000147 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000148 _tmmbr_Send(0),
149 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000150
151 _appSend(false),
152 _appSubType(0),
153 _appName(),
154 _appData(NULL),
155 _appLength(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000156
157 xrSendReceiverReferenceTimeEnabled_(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000158 _xrSendVoIPMetric(false),
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000159 _xrVoIPMetric()
niklase@google.com470e71d2011-07-07 08:21:25 +0000160{
161 memset(_CNAME, 0, sizeof(_CNAME));
162 memset(_lastSendReport, 0, sizeof(_lastSendReport));
163 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
niklase@google.com470e71d2011-07-07 08:21:25 +0000164}
165
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000166RTCPSender::~RTCPSender() {
167 delete [] _rembSSRC;
168 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000169
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000170 while (!internal_report_blocks_.empty()) {
171 delete internal_report_blocks_.begin()->second;
172 internal_report_blocks_.erase(internal_report_blocks_.begin());
173 }
174 while (!external_report_blocks_.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000175 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000176 external_report_blocks_.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000177 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000178 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000179 }
180 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000181 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000182 _csrcCNAMEs.begin();
183 delete it->second;
184 _csrcCNAMEs.erase(it);
185 }
186 delete _criticalSectionTransport;
187 delete _criticalSectionRTCPSender;
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
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000225 xrSendReceiverReferenceTimeEnabled_ = false;
226
niklase@google.com470e71d2011-07-07 08:21:25 +0000227 _xrSendVoIPMetric = false;
228
229 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
230 memset(_CNAME, 0, sizeof(_CNAME));
231 memset(_lastSendReport, 0, sizeof(_lastSendReport));
232 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000233 last_xr_rr_.clear();
edjee@google.com79b02892013-04-04 19:43:34 +0000234
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000235 memset(&packet_type_counter_, 0, sizeof(packet_type_counter_));
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;
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000347 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
348 // throttled by the caller.
349 _nextTimeToSendRTCP = _clock->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000350 return 0;
351}
352
353bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000354RTCPSender::TMMBR() const
355{
356 CriticalSectionScoped lock(_criticalSectionRTCPSender);
357 return _TMMBR;
358}
359
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000360int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000361RTCPSender::SetTMMBRStatus(const bool enable)
362{
363 CriticalSectionScoped lock(_criticalSectionRTCPSender);
364 _TMMBR = enable;
365 return 0;
366}
367
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000368bool
369RTCPSender::IJ() const
370{
371 CriticalSectionScoped lock(_criticalSectionRTCPSender);
372 return _IJ;
373}
374
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000375int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000376RTCPSender::SetIJStatus(const bool enable)
377{
378 CriticalSectionScoped lock(_criticalSectionRTCPSender);
379 _IJ = enable;
380 return 0;
381}
382
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000383void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
384 start_timestamp_ = start_timestamp;
385}
386
387void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
388 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000389 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000390 last_rtp_timestamp_ = rtp_timestamp;
391 if (capture_time_ms < 0) {
392 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000393 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000394 } else {
395 last_frame_capture_time_ms_ = capture_time_ms;
396 }
397}
398
niklase@google.com470e71d2011-07-07 08:21:25 +0000399void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000400RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000401{
402 CriticalSectionScoped lock(_criticalSectionRTCPSender);
403
404 if(_SSRC != 0)
405 {
406 // not first SetSSRC, probably due to a collision
407 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000408 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000409 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000410 }
411 _SSRC = ssrc;
412}
413
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000414void RTCPSender::SetRemoteSSRC(uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000415{
416 CriticalSectionScoped lock(_criticalSectionRTCPSender);
417 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000418}
419
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000420int32_t
421RTCPSender::SetCameraDelay(const int32_t delayMS)
422{
423 CriticalSectionScoped lock(_criticalSectionRTCPSender);
424 if(delayMS > 1000 || delayMS < -1000)
425 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000426 LOG(LS_WARNING) << "Delay can't be larger than 1 second: "
427 << delayMS << " ms";
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000428 return -1;
429 }
430 _cameraDelayMS = delayMS;
431 return 0;
432}
433
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000434int32_t RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000435 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000436 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000437 cName[RTCP_CNAME_SIZE - 1] = 0;
438 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000439 return 0;
440}
441
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000442int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000443 if (!cName)
444 return -1;
445
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000446 CriticalSectionScoped lock(_criticalSectionRTCPSender);
447 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
448 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
449 return 0;
450}
451
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000452int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
453 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000454 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000455 CriticalSectionScoped lock(_criticalSectionRTCPSender);
456 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
457 return -1;
458 }
459 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000460 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
461 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000462 _csrcCNAMEs[SSRC] = ptr;
463 return 0;
464}
465
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000466int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000467 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000468 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000469 _csrcCNAMEs.find(SSRC);
470
471 if (it == _csrcCNAMEs.end()) {
472 return -1;
473 }
474 delete it->second;
475 _csrcCNAMEs.erase(it);
476 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000477}
478
479bool
480RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
481{
482/*
483 For audio we use a fix 5 sec interval
484
485 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000486 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
487 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000488
489
490From RFC 3550
491
492 MAX RTCP BW is 5% if the session BW
493 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000494 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000495
496 The RECOMMENDED value for the reduced minimum in seconds is 360
497 divided by the session bandwidth in kilobits/second. This minimum
498 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
499
500 If the participant has not yet sent an RTCP packet (the variable
501 initial is true), the constant Tmin is set to 2.5 seconds, else it
502 is set to 5 seconds.
503
504 The interval between RTCP packets is varied randomly over the
505 range [0.5,1.5] times the calculated interval to avoid unintended
506 synchronization of all participants
507
508 if we send
509 If the participant is a sender (we_sent true), the constant C is
510 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
511 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
512 number of senders.
513
514 if we receive only
515 If we_sent is not true, the constant C is set
516 to the average RTCP packet size divided by 75% of the RTCP
517 bandwidth. The constant n is set to the number of receivers
518 (members - senders). If the number of senders is greater than
519 25%, senders and receivers are treated together.
520
521 reconsideration NOT required for peer-to-peer
522 "timer reconsideration" is
523 employed. This algorithm implements a simple back-off mechanism
524 which causes users to hold back RTCP packet transmission if the
525 group sizes are increasing.
526
527 n = number of members
528 C = avg_size/(rtcpBW/4)
529
530 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
531
532 4. The calculated interval T is set to a number uniformly distributed
533 between 0.5 and 1.5 times the deterministic calculated interval.
534
535 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
536 for the fact that the timer reconsideration algorithm converges to
537 a value of the RTCP bandwidth below the intended average
538*/
539
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000540 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000541
542 CriticalSectionScoped lock(_criticalSectionRTCPSender);
543
niklase@google.com470e71d2011-07-07 08:21:25 +0000544 if(_method == kRtcpOff)
545 {
546 return false;
547 }
548
niklase@google.com470e71d2011-07-07 08:21:25 +0000549 if(!_audio && sendKeyframeBeforeRTP)
550 {
551 // for video key-frames we want to send the RTCP before the large key-frame
552 // if we have a 100 ms margin
553 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
554 }
555
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000556 if(now >= _nextTimeToSendRTCP)
niklase@google.com470e71d2011-07-07 08:21:25 +0000557 {
558 return true;
559
560 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
561 {
562 // wrap
563 return true;
564 }
565 return false;
566}
567
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000568uint32_t
569RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000570{
571 CriticalSectionScoped lock(_criticalSectionRTCPSender);
572
573 lastRTCPTime = _lastRTCPTime[0];
574 return _lastSendReport[0];
575}
576
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000577uint32_t
578RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000579{
580 CriticalSectionScoped lock(_criticalSectionRTCPSender);
581
582 // This is only saved when we are the sender
583 if((_lastSendReport[0] == 0) || (sendReport == 0))
584 {
585 return 0; // will be ignored
586 } else
587 {
588 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
589 {
590 if( _lastSendReport[i] == sendReport)
591 {
592 return _lastRTCPTime[i];
593 }
594 }
595 }
596 return 0;
597}
598
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000599bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
600 int64_t* time_ms) const {
601 CriticalSectionScoped lock(_criticalSectionRTCPSender);
602
603 if (last_xr_rr_.empty()) {
604 return false;
605 }
606 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
607 if (it == last_xr_rr_.end()) {
608 return false;
609 }
610 *time_ms = it->second;
611 return true;
612}
613
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000614void RTCPSender::GetPacketTypeCounter(
615 RtcpPacketTypeCounter* packet_counter) const {
616 CriticalSectionScoped lock(_criticalSectionRTCPSender);
617 *packet_counter = packet_type_counter_;
618}
619
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000620int32_t RTCPSender::AddExternalReportBlock(
621 uint32_t SSRC,
622 const RTCPReportBlock* reportBlock) {
623 CriticalSectionScoped lock(_criticalSectionRTCPSender);
624 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
625}
626
627int32_t RTCPSender::AddReportBlock(
628 uint32_t SSRC,
629 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
630 const RTCPReportBlock* reportBlock) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000631 assert(reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000632
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000633 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000634 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000635 return -1;
636 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000637 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000638 report_blocks->find(SSRC);
639 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000640 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000641 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000642 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000643 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
644 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000645 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000646 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000647}
648
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000649int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000650 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000651
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000652 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000653 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000654
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000655 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000656 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000657 }
658 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000659 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000660 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000661}
662
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000663int32_t RTCPSender::BuildSR(const FeedbackState& feedback_state,
664 uint8_t* rtcpbuffer,
665 int& pos,
666 uint32_t NTPsec,
667 uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000668{
669 // sanity
670 if(pos + 52 >= IP_PACKET_SIZE)
671 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000672 LOG(LS_WARNING) << "Failed to build Sender Report.";
niklase@google.com470e71d2011-07-07 08:21:25 +0000673 return -2;
674 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000675 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000676
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000677 uint32_t posNumberOfReportBlocks = pos;
678 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000679
680 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000681 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000682
683 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
684 {
685 // shift old
686 _lastSendReport[i+1] = _lastSendReport[i];
687 _lastRTCPTime[i+1] =_lastRTCPTime[i];
688 }
689
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000690 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000691 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000692
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000693 // The timestamp of this RTCP packet should be estimated as the timestamp of
694 // the frame being captured at this moment. We are calculating that
695 // timestamp as the last frame's timestamp + the time since the last frame
696 // was captured.
697 {
698 // Needs protection since this method is called on the process thread.
699 CriticalSectionScoped lock(_criticalSectionRTCPSender);
700 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
701 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000702 (feedback_state.frequency_hz / 1000);
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000703 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000704
705 // Add sender data
706 // Save for our length field
707 pos++;
708 pos++;
709
710 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000711 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000712 pos += 4;
713 // NTP
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000714 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000715 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000716 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000717 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000718 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, RTPtime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000719 pos += 4;
720
721 //sender's packet count
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000722 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
723 feedback_state.packet_count_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000724 pos += 4;
725
726 //sender's octet count
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000727 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
728 feedback_state.byte_count_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000729 pos += 4;
730
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000731 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000732 int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
733 numberOfReportBlocks,
734 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000735 if(retVal < 0)
736 {
737 //
738 return retVal ;
739 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000740 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000741 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
742
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000743 uint16_t len = uint16_t((pos/4) -1);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000744 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000745 return 0;
746}
747
748
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000749int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000750 size_t lengthCname = strlen(_CNAME);
751 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000752
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000753 // sanity
754 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000755 LOG(LS_WARNING) << "Failed to build SDEC.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000756 return -2;
757 }
758 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000759
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000760 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000761 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
762 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000763
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000764 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000765 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000766 pos++;
767 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000768
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000769 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000770 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000771 pos += 4;
772
773 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000774 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000775
776 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000777 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000778
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000779 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000780
781 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
782 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000783 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000784
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000785 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000786 // We must have a zero field even if we have an even multiple of 4 bytes
787 if ((pos % 4) == 0) {
788 padding++;
789 rtcpbuffer[pos++]=0;
790 }
791 while ((pos % 4) != 0) {
792 padding++;
793 rtcpbuffer[pos++]=0;
794 }
795 SDESLength += padding;
796
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000797 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000798 _csrcCNAMEs.begin();
799
800 for(; it != _csrcCNAMEs.end(); it++) {
801 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000802 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000803
804 // Add SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000805 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000806 pos += 4;
807
808 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000809 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000810
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000811 size_t length = strlen(cname->name);
812 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000813
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000814 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000815 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000816
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000817 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000818
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000819 pos += length;
820 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000821 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000822
823 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000824 if((pos % 4) == 0){
825 padding++;
826 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000827 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000828 while((pos % 4) != 0){
829 padding++;
830 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000831 }
832 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000833 }
834 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000835 uint16_t buffer_length = (SDESLength / 4) - 1;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000836 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos, buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000837 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000838}
839
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000840int32_t
841RTCPSender::BuildRR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000842 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000843 const uint32_t NTPsec,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000844 const uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000845{
846 // sanity one block
847 if(pos + 32 >= IP_PACKET_SIZE)
848 {
849 return -2;
850 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000851 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000852
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000853 rtcpbuffer[pos++]=(uint8_t)0x80;
854 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000855
856 // Save for our length field
857 pos++;
858 pos++;
859
860 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000861 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000862 pos += 4;
863
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000864 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000865 int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
866 numberOfReportBlocks,
867 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000868 if(retVal < 0)
869 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000870 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000871 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000872 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000873 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
874
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000875 uint16_t len = uint16_t((pos)/4 -1);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000876 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000877 return 0;
878}
879
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000880// From RFC 5450: Transmission Time Offsets in RTP Streams.
881// 0 1 2 3
882// 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
883// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
884// hdr |V=2|P| RC | PT=IJ=195 | length |
885// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
886// | inter-arrival jitter |
887// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
888// . .
889// . .
890// . .
891// | inter-arrival jitter |
892// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
893//
894// If present, this RTCP packet must be placed after a receiver report
895// (inside a compound RTCP packet), and MUST have the same value for RC
896// (reception report count) as the receiver report.
897
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000898int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000899RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000900 uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000901 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000902 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000903{
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000904 if (external_report_blocks_.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000905 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000906 // TODO(andresp): Remove external report blocks since they are not
907 // supported.
908 LOG(LS_ERROR) << "Handling of external report blocks not implemented.";
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000909 return 0;
910 }
911
912 // sanity
913 if(pos + 8 >= IP_PACKET_SIZE)
914 {
915 return -2;
916 }
917 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000918 uint8_t RC = 1;
919 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
920 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000921
922 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000923 rtcpbuffer[pos++]=(uint8_t)0;
924 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000925
926 // Add inter-arrival jitter
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000927 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
928 jitterTransmissionTimeOffset);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000929 pos += 4;
930 return 0;
931}
932
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000933int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000934RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000935{
936 // sanity
937 if(pos + 12 >= IP_PACKET_SIZE)
938 {
939 return -2;
940 }
941 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000942 uint8_t FMT = 1;
943 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
944 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000945
946 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000947 rtcpbuffer[pos++]=(uint8_t)0;
948 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000949
950 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000951 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000952 pos += 4;
953
954 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000955 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000956 pos += 4;
957 return 0;
958}
959
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000960int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000961 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000962 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000963 // sanity
964 if(pos + 20 >= IP_PACKET_SIZE) {
965 return -2;
966 }
967 if (!repeat) {
968 _sequenceNumberFIR++; // do not increase if repetition
969 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000970
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000971 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000972 uint8_t FMT = 4;
973 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
974 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000975
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000976 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000977 rtcpbuffer[pos++] = (uint8_t)0;
978 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000979
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000980 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000981 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000982 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000983
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000984 // RFC 5104 4.3.1.2. Semantics
985 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000986 rtcpbuffer[pos++] = (uint8_t)0;
987 rtcpbuffer[pos++] = (uint8_t)0;
988 rtcpbuffer[pos++] = (uint8_t)0;
989 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000990
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000991 // Additional Feedback Control Information (FCI)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000992 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000993 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000994
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000995 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
996 rtcpbuffer[pos++] = (uint8_t)0;
997 rtcpbuffer[pos++] = (uint8_t)0;
998 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000999 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001000}
1001
1002/*
1003 0 1 2 3
1004 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
1005 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1006 | First | Number | PictureID |
1007 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1008*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001009int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001010RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +00001011{
1012 // sanity
1013 if(pos + 16 >= IP_PACKET_SIZE)
1014 {
1015 return -2;
1016 }
1017 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001018 uint8_t FMT = 2;
1019 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1020 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001021
1022 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001023 rtcpbuffer[pos++]=(uint8_t)0;
1024 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +00001025
1026 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001027 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001028 pos += 4;
1029
1030 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001031 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001032 pos += 4;
1033
1034 // Add first, number & picture ID 6 bits
1035 // first = 0, 13 - bits
1036 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001037 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001038 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, sliField);
niklase@google.com470e71d2011-07-07 08:21:25 +00001039 pos += 4;
1040 return 0;
1041}
1042
1043/*
1044 0 1 2 3
1045 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
1046 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1047 | PB |0| Payload Type| Native RPSI bit string |
1048 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1049 | defined per codec ... | Padding (0) |
1050 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1051*/
1052/*
1053* Note: not generic made for VP8
1054*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001055int32_t
1056RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001057 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001058 const uint64_t pictureID,
1059 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +00001060{
1061 // sanity
1062 if(pos + 24 >= IP_PACKET_SIZE)
1063 {
1064 return -2;
1065 }
1066 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001067 uint8_t FMT = 3;
1068 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1069 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001070
1071 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001072 uint32_t bitsRequired = 7;
1073 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001074 while((pictureID>>bitsRequired) > 0)
1075 {
1076 bitsRequired += 7;
1077 bytesRequired++;
1078 }
1079
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001080 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001081 if(bytesRequired > 6)
1082 {
1083 size = 5;
1084 } else if(bytesRequired > 2)
1085 {
1086 size = 4;
1087 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001088 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001089 rtcpbuffer[pos++]=size;
1090
1091 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001092 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001093 pos += 4;
1094
1095 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001096 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001097 pos += 4;
1098
1099 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001100 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001101 if(paddingBytes == 4)
1102 {
1103 paddingBytes = 0;
1104 }
1105 // add padding length in bits
1106 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1107 pos++;
1108
1109 // add payload type
1110 rtcpbuffer[pos] = payloadType;
1111 pos++;
1112
1113 // add picture ID
1114 for(int i = bytesRequired-1; i > 0; i--)
1115 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001116 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001117 pos++;
1118 }
1119 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001120 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001121 pos++;
1122
1123 // add padding
1124 for(int j = 0; j <paddingBytes; j++)
1125 {
1126 rtcpbuffer[pos] = 0;
1127 pos++;
1128 }
1129 return 0;
1130}
1131
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001132int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001133RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001134{
1135 // sanity
1136 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1137 {
1138 return -2;
1139 }
1140 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001141 uint8_t FMT = 15;
1142 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1143 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001144
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001145 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001146 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1147
1148 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001149 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001150 pos += 4;
1151
1152 // Remote SSRC must be 0
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001153 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, 0);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001154 pos += 4;
1155
1156 rtcpbuffer[pos++]='R';
1157 rtcpbuffer[pos++]='E';
1158 rtcpbuffer[pos++]='M';
1159 rtcpbuffer[pos++]='B';
1160
1161 rtcpbuffer[pos++] = _lengthRembSSRC;
1162 // 6 bit Exp
1163 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001164 uint8_t brExp = 0;
1165 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001166 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001167 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001168 {
1169 brExp = i;
1170 break;
1171 }
1172 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001173 const uint32_t brMantissa = (_rembBitrate >> brExp);
1174 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1175 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1176 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001177
1178 for (int i = 0; i < _lengthRembSSRC; i++)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001179 {
1180 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _rembSSRC[i]);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001181 pos += 4;
1182 }
1183 return 0;
1184}
1185
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001186void
1187RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001188{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001189 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001190 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001191}
1192
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001193int32_t RTCPSender::BuildTMMBR(ModuleRtpRtcpImpl* rtp_rtcp_module,
1194 uint8_t* rtcpbuffer,
1195 int& pos) {
1196 if (rtp_rtcp_module == NULL)
1197 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001198 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1199 // If the sender is an owner of the TMMBN -> send TMMBR
1200 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1201
niklase@google.com470e71d2011-07-07 08:21:25 +00001202 // get current bounding set from RTCP receiver
1203 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001204 // store in candidateSet, allocates one extra slot
1205 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001206
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001207 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1208 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1209 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001210 int32_t lengthOfBoundingSet =
1211 rtp_rtcp_module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001212
1213 if(lengthOfBoundingSet > 0)
1214 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001215 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001216 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001217 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1218 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001219 {
1220 // do not send the same tuple
1221 return 0;
1222 }
1223 }
1224 if(!tmmbrOwner)
1225 {
1226 // use received bounding set as candidate set
1227 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001228 candidateSet->SetEntry(lengthOfBoundingSet,
1229 _tmmbr_Send,
1230 _packetOH_Send,
1231 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001232 int numCandidates = lengthOfBoundingSet+ 1;
1233
1234 // find bounding set
1235 TMMBRSet* boundingSet = NULL;
1236 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1237 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1238 {
1239 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1240 }
1241 if(!tmmbrOwner)
1242 {
1243 // did not enter bounding set, no meaning to send this request
1244 return 0;
1245 }
1246 }
1247 }
1248
1249 if(_tmmbr_Send)
1250 {
1251 // sanity
1252 if(pos + 20 >= IP_PACKET_SIZE)
1253 {
1254 return -2;
1255 }
1256 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001257 uint8_t FMT = 3;
1258 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1259 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001260
1261 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001262 rtcpbuffer[pos++]=(uint8_t)0;
1263 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001264
1265 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001266 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001267 pos += 4;
1268
1269 // RFC 5104 4.2.1.2. Semantics
1270
1271 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001272 rtcpbuffer[pos++]=(uint8_t)0;
1273 rtcpbuffer[pos++]=(uint8_t)0;
1274 rtcpbuffer[pos++]=(uint8_t)0;
1275 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001276
1277 // Additional Feedback Control Information (FCI)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001278 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001279 pos += 4;
1280
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001281 uint32_t bitRate = _tmmbr_Send*1000;
1282 uint32_t mmbrExp = 0;
1283 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001284 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001285 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001286 {
1287 mmbrExp = i;
1288 break;
1289 }
1290 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001291 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001292
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001293 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1294 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1295 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1296 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001297 }
1298 return 0;
1299}
1300
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001301int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001302RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001303{
1304 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1305 if(boundingSet == NULL)
1306 {
1307 return -1;
1308 }
1309 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001310 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001311 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001312 LOG(LS_WARNING) << "Failed to build TMMBN.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001313 return -2;
1314 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001315 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001316 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001317 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1318 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001319
1320 //Add length later
1321 int posLength = pos;
1322 pos++;
1323 pos++;
1324
1325 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001326 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001327 pos += 4;
1328
1329 // RFC 5104 4.2.2.2. Semantics
1330
1331 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001332 rtcpbuffer[pos++]=(uint8_t)0;
1333 rtcpbuffer[pos++]=(uint8_t)0;
1334 rtcpbuffer[pos++]=(uint8_t)0;
1335 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001336
1337 // Additional Feedback Control Information (FCI)
1338 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001339 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001340 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001341 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001342 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001343 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001344 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, tmmbrSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001345 pos += 4;
1346
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001347 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1348 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001349 for(int i=0; i<64; i++)
1350 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001351 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001352 {
1353 mmbrExp = i;
1354 break;
1355 }
1356 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001357 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1358 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001359
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001360 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1361 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1362 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1363 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001364 numBoundingSet++;
1365 }
1366 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001367 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1368 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1369 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001370 return 0;
1371}
1372
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001373int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001374RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001375{
1376 // sanity
1377 if(_appData == NULL)
1378 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001379 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001380 return -1;
1381 }
1382 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1383 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001384 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001385 return -2;
1386 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001387 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001388
1389 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001390 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001391
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001392 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1393 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1394 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001395
1396 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001397 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001398 pos += 4;
1399
1400 // Add our application name
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001401 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _appName);
niklase@google.com470e71d2011-07-07 08:21:25 +00001402 pos += 4;
1403
1404 // Add the data
1405 memcpy(rtcpbuffer +pos, _appData,_appLength);
1406 pos += _appLength;
1407 return 0;
1408}
1409
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001410int32_t
1411RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001412 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001413 const int32_t nackSize,
1414 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001415 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001416{
1417 // sanity
1418 if(pos + 16 >= IP_PACKET_SIZE)
1419 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001420 LOG(LS_WARNING) << "Failed to build NACK.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001421 return -2;
1422 }
1423
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001424 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001425 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001426 uint8_t FMT = 1;
1427 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1428 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001429
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001430 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001431 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001432 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001433
1434 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001435 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001436 pos += 4;
1437
1438 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001439 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001440 pos += 4;
1441
edjee@google.com79b02892013-04-04 19:43:34 +00001442 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001443 // Build NACK bitmasks and write them to the RTCP message.
1444 // The nack list should be sorted and not contain duplicates if one
1445 // wants to build the smallest rtcp nack packet.
1446 int numOfNackFields = 0;
1447 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1448 (IP_PACKET_SIZE - pos) / 4);
1449 int i = 0;
1450 while (i < nackSize && numOfNackFields < maxNackFields) {
1451 stringBuilder.PushNACK(nackList[i]);
1452 uint16_t nack = nackList[i++];
1453 uint16_t bitmask = 0;
1454 while (i < nackSize) {
1455 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1456 if (shift >= 0 && shift <= 15) {
1457 stringBuilder.PushNACK(nackList[i]);
1458 bitmask |= (1 << shift);
1459 ++i;
1460 } else {
1461 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001462 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001463 }
1464 // Write the sequence number and the bitmask to the packet.
1465 assert(pos + 4 < IP_PACKET_SIZE);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001466 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001467 pos += 2;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001468 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001469 pos += 2;
1470 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001471 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001472 if (i != nackSize) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001473 LOG(LS_WARNING) << "Nack list to large for one packet.";
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001474 }
1475 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001476 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001477 return 0;
1478}
1479
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001480int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001481RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001482{
1483 // sanity
1484 if(pos + 8 >= IP_PACKET_SIZE)
1485 {
1486 return -2;
1487 }
1488 if(_includeCSRCs)
1489 {
1490 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001491 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // 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 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001497
1498 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001499 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001500 pos += 4;
1501
1502 // add CSRCs
1503 for(int i = 0; i < _CSRCs; i++)
1504 {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001505 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _CSRC[i]);
niklase@google.com470e71d2011-07-07 08:21:25 +00001506 pos += 4;
1507 }
1508 } else
1509 {
1510 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001511 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1512 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001513
1514 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001515 rtcpbuffer[pos++]=(uint8_t)0;
1516 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001517
1518 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001519 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001520 pos += 4;
1521 }
1522 return 0;
1523}
1524
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001525int32_t RTCPSender::BuildReceiverReferenceTime(uint8_t* buffer,
1526 int& pos,
1527 uint32_t ntp_sec,
1528 uint32_t ntp_frac) {
1529 const int kRrTimeBlockLength = 20;
1530 if (pos + kRrTimeBlockLength >= IP_PACKET_SIZE) {
1531 return -2;
1532 }
1533
1534 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) {
1535 last_xr_rr_.erase(last_xr_rr_.begin());
1536 }
1537 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
1538 RTCPUtility::MidNtp(ntp_sec, ntp_frac),
1539 Clock::NtpToMs(ntp_sec, ntp_frac)));
1540
1541 // Add XR header.
1542 buffer[pos++] = 0x80;
1543 buffer[pos++] = 207;
1544 buffer[pos++] = 0; // XR packet length.
1545 buffer[pos++] = 4; // XR packet length.
1546
1547 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001548 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001549 pos += 4;
1550
1551 // 0 1 2 3
1552 // 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
1553 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1554 // | BT=4 | reserved | block length = 2 |
1555 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1556 // | NTP timestamp, most significant word |
1557 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1558 // | NTP timestamp, least significant word |
1559 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1560
1561 // Add Receiver Reference Time Report block.
1562 buffer[pos++] = 4; // BT.
1563 buffer[pos++] = 0; // Reserved.
1564 buffer[pos++] = 0; // Block length.
1565 buffer[pos++] = 2; // Block length.
1566
1567 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001568 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_sec);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001569 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001570 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001571 pos += 4;
1572
1573 return 0;
1574}
1575
1576int32_t RTCPSender::BuildDlrr(uint8_t* buffer,
1577 int& pos,
1578 const RtcpReceiveTimeInfo& info) {
1579 const int kDlrrBlockLength = 24;
1580 if (pos + kDlrrBlockLength >= IP_PACKET_SIZE) {
1581 return -2;
1582 }
1583
1584 // Add XR header.
1585 buffer[pos++] = 0x80;
1586 buffer[pos++] = 207;
1587 buffer[pos++] = 0; // XR packet length.
1588 buffer[pos++] = 5; // XR packet length.
1589
1590 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001591 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001592 pos += 4;
1593
1594 // 0 1 2 3
1595 // 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
1596 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1597 // | BT=5 | reserved | block length |
1598 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1599 // | SSRC_1 (SSRC of first receiver) | sub-
1600 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1601 // | last RR (LRR) | 1
1602 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1603 // | delay since last RR (DLRR) |
1604 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1605 // | SSRC_2 (SSRC of second receiver) | sub-
1606 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1607 // : ... : 2
1608
1609 // Add DLRR sub block.
1610 buffer[pos++] = 5; // BT.
1611 buffer[pos++] = 0; // Reserved.
1612 buffer[pos++] = 0; // Block length.
1613 buffer[pos++] = 3; // Block length.
1614
1615 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001616 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.sourceSSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001617 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001618 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.lastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001619 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001620 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.delaySinceLastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001621 pos += 4;
1622
1623 return 0;
1624}
1625
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001626int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001627RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001628{
1629 // sanity
1630 if(pos + 44 >= IP_PACKET_SIZE)
1631 {
1632 return -2;
1633 }
1634
1635 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001636 rtcpbuffer[pos++]=(uint8_t)0x80;
1637 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001638
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001639 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001640
1641 // handle length later on
1642 pos++;
1643 pos++;
1644
1645 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001646 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001647 pos += 4;
1648
1649 // Add a VoIP metrics block
1650 rtcpbuffer[pos++]=7;
1651 rtcpbuffer[pos++]=0;
1652 rtcpbuffer[pos++]=0;
1653 rtcpbuffer[pos++]=8;
1654
1655 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001656 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001657 pos += 4;
1658
1659 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1660 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1661 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1662 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1663
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001664 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1665 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1666 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1667 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001668
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001669 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1670 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1671 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1672 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001673
1674 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1675 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1676 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1677 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1678
1679 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1680 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1681 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1682 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1683
1684 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1685 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001686 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1687 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001688
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001689 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1690 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1691 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1692 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001693
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001694 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1695 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001696 return 0;
1697}
1698
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001699int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
1700 uint32_t packetTypeFlags,
1701 int32_t nackSize,
1702 const uint16_t* nackList,
1703 bool repeat,
1704 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001705 {
1706 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1707 if(_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001708 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001709 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001710 return -1;
1711 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001712 }
1713 uint8_t rtcp_buffer[IP_PACKET_SIZE];
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001714 int rtcp_length = PrepareRTCP(feedback_state,
1715 packetTypeFlags,
1716 nackSize,
1717 nackList,
1718 repeat,
1719 pictureID,
1720 rtcp_buffer,
1721 IP_PACKET_SIZE);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001722 if (rtcp_length < 0) {
1723 return -1;
1724 }
1725 // Sanity don't send empty packets.
1726 if (rtcp_length == 0)
1727 {
1728 return -1;
1729 }
1730 return SendToNetwork(rtcp_buffer, static_cast<uint16_t>(rtcp_length));
1731}
1732
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001733int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
1734 uint32_t packetTypeFlags,
1735 int32_t nackSize,
1736 const uint16_t* nackList,
1737 bool repeat,
1738 uint64_t pictureID,
1739 uint8_t* rtcp_buffer,
1740 int buffer_size) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001741 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1742 // Collect the received information.
1743 uint32_t NTPsec = 0;
1744 uint32_t NTPfrac = 0;
1745 uint32_t jitterTransmissionOffset = 0;
1746 int position = 0;
1747
1748 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1749
1750 if(_TMMBR ) // Attach TMMBR to send and receive reports.
1751 {
1752 rtcpPacketTypeFlags |= kRtcpTmmbr;
1753 }
1754 if(_appSend)
1755 {
1756 rtcpPacketTypeFlags |= kRtcpApp;
1757 _appSend = false;
1758 }
1759 if(_REMB && _sendREMB)
1760 {
1761 // Always attach REMB to SR if that is configured. Note that REMB is
1762 // only sent on one of the RTP modules in the REMB group.
1763 rtcpPacketTypeFlags |= kRtcpRemb;
1764 }
1765 if(_xrSendVoIPMetric)
1766 {
1767 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1768 _xrSendVoIPMetric = false;
1769 }
1770 if(_sendTMMBN) // Set when having received a TMMBR.
1771 {
1772 rtcpPacketTypeFlags |= kRtcpTmmbn;
1773 _sendTMMBN = false;
1774 }
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001775 if (rtcpPacketTypeFlags & kRtcpReport)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001776 {
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001777 if (xrSendReceiverReferenceTimeEnabled_ && !_sending)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001778 {
1779 rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
1780 }
1781 if (feedback_state.has_last_xr_rr)
1782 {
1783 rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
1784 }
1785 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001786 if(_method == kRtcpCompound)
1787 {
1788 if(_sending)
1789 {
1790 rtcpPacketTypeFlags |= kRtcpSr;
1791 } else
1792 {
1793 rtcpPacketTypeFlags |= kRtcpRr;
1794 }
1795 } else if(_method == kRtcpNonCompound)
1796 {
1797 if(rtcpPacketTypeFlags & kRtcpReport)
1798 {
1799 if(_sending)
1800 {
1801 rtcpPacketTypeFlags |= kRtcpSr;
1802 } else
1803 {
1804 rtcpPacketTypeFlags |= kRtcpRr;
1805 }
1806 }
1807 }
1808 if( rtcpPacketTypeFlags & kRtcpRr ||
1809 rtcpPacketTypeFlags & kRtcpSr)
1810 {
1811 // generate next time to send a RTCP report
1812 // seeded from RTP constructor
1813 int32_t random = rand() % 1000;
1814 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1815
1816 if(_audio)
1817 {
1818 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1819 (RTCP_INTERVAL_AUDIO_MS*random/1000);
1820 }else
1821 {
1822 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1823 if(_sending)
1824 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001825 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1826 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1827 if (send_bitrate_kbit != 0)
1828 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001829 }
1830 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1831 {
1832 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1833 }
1834 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1835 }
1836 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1837 }
1838
1839 // If the data does not fit in the packet we fill it as much as possible.
1840 int32_t buildVal = 0;
1841
1842 // We need to send our NTP even if we haven't received any reports.
1843 _clock->CurrentNtp(NTPsec, NTPfrac);
1844 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1845 StatisticianMap statisticians =
1846 receive_statistics_->GetActiveStatisticians();
1847 if (!statisticians.empty()) {
1848 StatisticianMap::const_iterator it;
1849 int i;
1850 for (it = statisticians.begin(), i = 0; it != statisticians.end();
1851 ++it, ++i) {
1852 RTCPReportBlock report_block;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001853 if (PrepareReport(
1854 feedback_state, it->second, &report_block, &NTPsec, &NTPfrac))
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001855 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1856 }
1857 if (_IJ && !statisticians.empty()) {
1858 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1859 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001860 }
1861 }
1862
1863 if(rtcpPacketTypeFlags & kRtcpSr)
1864 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001865 buildVal = BuildSR(feedback_state, rtcp_buffer, position, NTPsec, NTPfrac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001866 if (buildVal == -1) {
1867 return -1;
1868 } else if (buildVal == -2) {
1869 return position;
1870 }
1871 buildVal = BuildSDEC(rtcp_buffer, position);
1872 if (buildVal == -1) {
1873 return -1;
1874 } else if (buildVal == -2) {
1875 return position;
1876 }
1877 }else if(rtcpPacketTypeFlags & kRtcpRr)
1878 {
1879 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1880 if (buildVal == -1) {
1881 return -1;
1882 } else if (buildVal == -2) {
1883 return position;
1884 }
1885 // only of set
1886 if(_CNAME[0] != 0)
1887 {
1888 buildVal = BuildSDEC(rtcp_buffer, position);
1889 if (buildVal == -1) {
1890 return -1;
1891 }
1892 }
1893 }
1894 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1895 {
1896 // If present, this RTCP packet must be placed after a
1897 // receiver report.
1898 buildVal = BuildExtendedJitterReport(rtcp_buffer,
1899 position,
1900 jitterTransmissionOffset);
1901 if (buildVal == -1) {
1902 return -1;
1903 } else if (buildVal == -2) {
1904 return position;
1905 }
1906 }
1907 if(rtcpPacketTypeFlags & kRtcpPli)
1908 {
1909 buildVal = BuildPLI(rtcp_buffer, position);
1910 if (buildVal == -1) {
1911 return -1;
1912 } else if (buildVal == -2) {
1913 return position;
1914 }
1915 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001916 ++packet_type_counter_.pli_packets;
1917 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC,
1918 packet_type_counter_.pli_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001919 }
1920 if(rtcpPacketTypeFlags & kRtcpFir)
1921 {
1922 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1923 if (buildVal == -1) {
1924 return -1;
1925 } else if (buildVal == -2) {
1926 return position;
1927 }
1928 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001929 ++packet_type_counter_.fir_packets;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001930 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001931 packet_type_counter_.fir_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001932 }
1933 if(rtcpPacketTypeFlags & kRtcpSli)
1934 {
1935 buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1936 if (buildVal == -1) {
1937 return -1;
1938 } else if (buildVal == -2) {
1939 return position;
1940 }
1941 }
1942 if(rtcpPacketTypeFlags & kRtcpRpsi)
1943 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001944 const int8_t payloadType = feedback_state.send_payload_type;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001945 if (payloadType == -1) {
1946 return -1;
1947 }
1948 buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1949 (uint8_t)payloadType);
1950 if (buildVal == -1) {
1951 return -1;
1952 } else if (buildVal == -2) {
1953 return position;
1954 }
1955 }
1956 if(rtcpPacketTypeFlags & kRtcpRemb)
1957 {
1958 buildVal = BuildREMB(rtcp_buffer, position);
1959 if (buildVal == -1) {
1960 return -1;
1961 } else if (buildVal == -2) {
1962 return position;
1963 }
1964 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1965 }
1966 if(rtcpPacketTypeFlags & kRtcpBye)
1967 {
1968 buildVal = BuildBYE(rtcp_buffer, position);
1969 if (buildVal == -1) {
1970 return -1;
1971 } else if (buildVal == -2) {
1972 return position;
1973 }
1974 }
1975 if(rtcpPacketTypeFlags & kRtcpApp)
1976 {
1977 buildVal = BuildAPP(rtcp_buffer, position);
1978 if (buildVal == -1) {
1979 return -1;
1980 } else if (buildVal == -2) {
1981 return position;
1982 }
1983 }
1984 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1985 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001986 buildVal = BuildTMMBR(feedback_state.module, rtcp_buffer, position);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001987 if (buildVal == -1) {
1988 return -1;
1989 } else if (buildVal == -2) {
1990 return position;
1991 }
1992 }
1993 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1994 {
1995 buildVal = BuildTMMBN(rtcp_buffer, position);
1996 if (buildVal == -1) {
1997 return -1;
1998 } else if (buildVal == -2) {
1999 return position;
2000 }
2001 }
2002 if(rtcpPacketTypeFlags & kRtcpNack)
2003 {
2004 std::string nackString;
2005 buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
2006 &nackString);
2007 if (buildVal == -1) {
2008 return -1;
2009 } else if (buildVal == -2) {
2010 return position;
2011 }
2012 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
2013 "nacks", TRACE_STR_COPY(nackString.c_str()));
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00002014 ++packet_type_counter_.nack_packets;
2015 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC,
2016 packet_type_counter_.nack_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002017 }
2018 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
2019 {
2020 buildVal = BuildVoIPMetric(rtcp_buffer, position);
2021 if (buildVal == -1) {
2022 return -1;
2023 } else if (buildVal == -2) {
2024 return position;
2025 }
2026 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002027 if (rtcpPacketTypeFlags & kRtcpXrReceiverReferenceTime)
2028 {
2029 buildVal = BuildReceiverReferenceTime(rtcp_buffer,
2030 position,
2031 NTPsec,
2032 NTPfrac);
2033 if (buildVal == -1) {
2034 return -1;
2035 } else if (buildVal == -2) {
2036 return position;
2037 }
2038 }
2039 if (rtcpPacketTypeFlags & kRtcpXrDlrrReportBlock)
2040 {
2041 buildVal = BuildDlrr(rtcp_buffer, position, feedback_state.last_xr_rr);
2042 if (buildVal == -1) {
2043 return -1;
2044 } else if (buildVal == -2) {
2045 return position;
2046 }
2047 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002048 return position;
2049}
2050
2051bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
2052 return Status() == kRtcpCompound ||
2053 (rtcp_packet_type & kRtcpReport) ||
2054 (rtcp_packet_type & kRtcpSr) ||
2055 (rtcp_packet_type & kRtcpRr);
2056}
2057
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002058bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
2059 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002060 RTCPReportBlock* report_block,
2061 uint32_t* ntp_secs, uint32_t* ntp_frac) {
2062 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00002063 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002064 if (!statistician->GetStatistics(&stats, true))
2065 return false;
2066 report_block->fractionLost = stats.fraction_lost;
2067 report_block->cumulativeLost = stats.cumulative_lost;
2068 report_block->extendedHighSeqNum =
2069 stats.extended_max_sequence_number;
2070 report_block->jitter = stats.jitter;
2071
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002072 // get our NTP as late as possible to avoid a race
2073 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
2074
2075 // Delay since last received report
2076 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002077 if ((feedback_state.last_rr_ntp_secs != 0) ||
2078 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002079 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
2080 uint32_t now=*ntp_secs&0x0000FFFF;
2081 now <<=16;
2082 now += (*ntp_frac&0xffff0000)>>16;
2083
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002084 uint32_t receiveTime = feedback_state.last_rr_ntp_secs&0x0000FFFF;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002085 receiveTime <<=16;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002086 receiveTime += (feedback_state.last_rr_ntp_frac&0xffff0000)>>16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002087
2088 delaySinceLastReceivedSR = now-receiveTime;
2089 }
2090 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002091 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002092 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00002093}
2094
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002095int32_t
2096RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
2097 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002098{
2099 CriticalSectionScoped lock(_criticalSectionTransport);
2100 if(_cbTransport)
2101 {
2102 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
2103 {
2104 return 0;
2105 }
2106 }
2107 return -1;
2108}
2109
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002110int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002111RTCPSender::SetCSRCStatus(const bool include)
2112{
2113 _includeCSRCs = include;
2114 return 0;
2115}
2116
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002117int32_t
2118RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
2119 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00002120{
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002121 assert(arrLength <= kRtpCsrcSize);
niklase@google.com470e71d2011-07-07 08:21:25 +00002122 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2123
2124 for(int i = 0; i < arrLength;i++)
2125 {
2126 _CSRC[i] = arrOfCSRC[i];
2127 }
2128 _CSRCs = arrLength;
2129 return 0;
2130}
2131
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002132int32_t
2133RTCPSender::SetApplicationSpecificData(const uint8_t subType,
2134 const uint32_t name,
2135 const uint8_t* data,
2136 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002137{
2138 if(length %4 != 0)
2139 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002140 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
niklase@google.com470e71d2011-07-07 08:21:25 +00002141 return -1;
2142 }
2143 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2144
2145 if(_appData)
2146 {
2147 delete [] _appData;
2148 }
2149
2150 _appSend = true;
2151 _appSubType = subType;
2152 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002153 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002154 _appLength = length;
2155 memcpy(_appData, data, length);
2156 return 0;
2157}
2158
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002159int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002160RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2161{
2162 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2163 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2164
2165 _xrSendVoIPMetric = true;
2166 return 0;
2167}
2168
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002169void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
2170 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2171 xrSendReceiverReferenceTimeEnabled_ = enable;
2172}
2173
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00002174bool RTCPSender::RtcpXrReceiverReferenceTime() const {
2175 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2176 return xrSendReceiverReferenceTimeEnabled_;
2177}
2178
niklase@google.com470e71d2011-07-07 08:21:25 +00002179// called under critsect _criticalSectionRTCPSender
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002180int32_t RTCPSender::WriteAllReportBlocksToBuffer(
2181 uint8_t* rtcpbuffer,
2182 int pos,
2183 uint8_t& numberOfReportBlocks,
2184 const uint32_t NTPsec,
2185 const uint32_t NTPfrac) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002186 numberOfReportBlocks = external_report_blocks_.size();
2187 numberOfReportBlocks += internal_report_blocks_.size();
2188 if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002189 LOG(LS_WARNING) << "Can't fit all report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002190 return -1;
2191 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002192 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2193 while (!internal_report_blocks_.empty()) {
2194 delete internal_report_blocks_.begin()->second;
2195 internal_report_blocks_.erase(internal_report_blocks_.begin());
2196 }
2197 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2198 return pos;
2199}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002200
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002201int32_t RTCPSender::WriteReportBlocksToBuffer(
2202 uint8_t* rtcpbuffer,
2203 int32_t position,
2204 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2205 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2206 report_blocks.begin();
2207 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002208 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002209 RTCPReportBlock* reportBlock = it->second;
2210 if (reportBlock) {
2211 // Remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002212 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position, remoteSSRC);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002213 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002214
2215 // fraction lost
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002216 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002217
2218 // cumulative loss
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002219 RtpUtility::AssignUWord24ToBuffer(rtcpbuffer + position,
2220 reportBlock->cumulativeLost);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002221 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002222
2223 // extended highest seq_no, contain the highest sequence number received
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002224 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2225 reportBlock->extendedHighSeqNum);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002226 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002227
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002228 // Jitter
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002229 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2230 reportBlock->jitter);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002231 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002232
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002233 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2234 reportBlock->lastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002235 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002236
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002237 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2238 reportBlock->delaySinceLastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002239 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002240 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002241 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002242 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00002243}
2244
2245// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002246int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002247RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002248 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002249{
2250 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2251
2252 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2253 {
2254 _sendTMMBN = true;
2255 return 0;
2256 }
2257 return -1;
2258}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002259} // namespace webrtc