blob: 6e6edf8167877af2df6867fbb3b076778ecb23de [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> // assert
14#include <stdlib.h> // rand
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000015#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000017#include <algorithm> // min
18
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000019#include "webrtc/common_types.h"
20#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
21#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
22#include "webrtc/system_wrappers/interface/trace.h"
23#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000024
niklase@google.com470e71d2011-07-07 08:21:25 +000025namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000026
27using RTCPUtility::RTCPCnameInformation;
28
edjee@google.com79b02892013-04-04 19:43:34 +000029NACKStringBuilder::NACKStringBuilder() :
30 _stream(""), _count(0), _consecutive(false)
31{
32 // Empty.
33}
34
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000035NACKStringBuilder::~NACKStringBuilder() {}
36
pbos@webrtc.org2f446732013-04-08 11:08:41 +000037void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000038{
39 if (_count == 0)
40 {
41 _stream << nack;
42 } else if (nack == _prevNack + 1)
43 {
44 _consecutive = true;
45 } else
46 {
47 if (_consecutive)
48 {
49 _stream << "-" << _prevNack;
50 _consecutive = false;
51 }
52 _stream << "," << nack;
53 }
54 _count++;
55 _prevNack = nack;
56}
57
58std::string NACKStringBuilder::GetResult()
59{
60 if (_consecutive)
61 {
62 _stream << "-" << _prevNack;
63 _consecutive = false;
64 }
65 return _stream.str();
66}
67
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000068RTCPSender::FeedbackState::FeedbackState(ModuleRtpRtcpImpl* module)
69 : send_payload_type(module->SendPayloadType()),
70 frequency_hz(module->CurrentSendFrequencyHz()),
71 packet_count_sent(module->PacketCountSent()),
72 byte_count_sent(module->ByteCountSent()),
73 module(module) {
74 uint32_t last_ntp_secs = 0, last_ntp_frac = 0, last_remote_sr = 0;
75 module->LastReceivedNTP(last_ntp_secs, last_ntp_frac, last_remote_sr);
76 last_rr_ntp_secs = last_ntp_secs;
77 last_rr_ntp_frac = last_ntp_frac;
78 remote_sr = last_remote_sr;
79
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));
164
165 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
166}
167
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000168RTCPSender::~RTCPSender() {
169 delete [] _rembSSRC;
170 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000171
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000172 while (!internal_report_blocks_.empty()) {
173 delete internal_report_blocks_.begin()->second;
174 internal_report_blocks_.erase(internal_report_blocks_.begin());
175 }
176 while (!external_report_blocks_.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000177 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000178 external_report_blocks_.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000179 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000180 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000181 }
182 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000183 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000184 _csrcCNAMEs.begin();
185 delete it->second;
186 _csrcCNAMEs.erase(it);
187 }
188 delete _criticalSectionTransport;
189 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000190
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000191 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000192}
193
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000194int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000195RTCPSender::Init()
196{
197 CriticalSectionScoped lock(_criticalSectionRTCPSender);
198
199 _method = kRtcpOff;
200 _cbTransport = NULL;
201 _usingNack = false;
202 _sending = false;
203 _sendTMMBN = false;
204 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000205 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000206 _REMB = false;
207 _sendREMB = false;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000208 last_rtp_timestamp_ = 0;
209 last_frame_capture_time_ms_ = -1;
210 start_timestamp_ = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000211 _SSRC = 0;
212 _remoteSSRC = 0;
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000213 _cameraDelayMS = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000214 _sequenceNumberFIR = 0;
215 _tmmbr_Send = 0;
216 _packetOH_Send = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000217 _nextTimeToSendRTCP = 0;
218 _CSRCs = 0;
219 _appSend = false;
220 _appSubType = 0;
221
222 if(_appData)
223 {
224 delete [] _appData;
225 _appData = NULL;
226 }
227 _appLength = 0;
228
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000229 xrSendReceiverReferenceTimeEnabled_ = false;
230
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 _xrSendVoIPMetric = false;
232
233 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
234 memset(_CNAME, 0, sizeof(_CNAME));
235 memset(_lastSendReport, 0, sizeof(_lastSendReport));
236 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000237 last_xr_rr_.clear();
edjee@google.com79b02892013-04-04 19:43:34 +0000238
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000239 memset(&packet_type_counter_, 0, sizeof(packet_type_counter_));
niklase@google.com470e71d2011-07-07 08:21:25 +0000240 return 0;
241}
242
243void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000244RTCPSender::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +0000245{
246 _id = id;
247}
248
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000249int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000250RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
251{
252 CriticalSectionScoped lock(_criticalSectionTransport);
253 _cbTransport = outgoingTransport;
254 return 0;
255}
256
257RTCPMethod
258RTCPSender::Status() const
259{
260 CriticalSectionScoped lock(_criticalSectionRTCPSender);
261 return _method;
262}
263
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000264int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000265RTCPSender::SetRTCPStatus(const RTCPMethod method)
266{
267 CriticalSectionScoped lock(_criticalSectionRTCPSender);
268 if(method != kRtcpOff)
269 {
270 if(_audio)
271 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000272 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000273 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000274 } else
275 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000276 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000277 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000278 }
279 }
280 _method = method;
281 return 0;
282}
283
284bool
285RTCPSender::Sending() const
286{
287 CriticalSectionScoped lock(_criticalSectionRTCPSender);
288 return _sending;
289}
290
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000291int32_t
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000292RTCPSender::SetSendingStatus(const FeedbackState& feedback_state, bool sending)
niklase@google.com470e71d2011-07-07 08:21:25 +0000293{
294 bool sendRTCPBye = false;
295 {
296 CriticalSectionScoped lock(_criticalSectionRTCPSender);
297
298 if(_method != kRtcpOff)
299 {
300 if(sending == false && _sending == true)
301 {
302 // Trigger RTCP bye
303 sendRTCPBye = true;
304 }
305 }
306 _sending = sending;
307 }
308 if(sendRTCPBye)
309 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000310 return SendRTCP(feedback_state, kRtcpBye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000311 }
312 return 0;
313}
314
315bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000316RTCPSender::REMB() const
317{
318 CriticalSectionScoped lock(_criticalSectionRTCPSender);
319 return _REMB;
320}
321
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000322int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000323RTCPSender::SetREMBStatus(const bool enable)
324{
325 CriticalSectionScoped lock(_criticalSectionRTCPSender);
326 _REMB = enable;
327 return 0;
328}
329
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000330int32_t
331RTCPSender::SetREMBData(const uint32_t bitrate,
332 const uint8_t numberOfSSRC,
333 const uint32_t* SSRC)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000334{
335 CriticalSectionScoped lock(_criticalSectionRTCPSender);
336 _rembBitrate = bitrate;
337
338 if(_sizeRembSSRC < numberOfSSRC)
339 {
340 delete [] _rembSSRC;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000341 _rembSSRC = new uint32_t[numberOfSSRC];
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000342 _sizeRembSSRC = numberOfSSRC;
343 }
344
345 _lengthRembSSRC = numberOfSSRC;
346 for (int i = 0; i < numberOfSSRC; i++)
347 {
348 _rembSSRC[i] = SSRC[i];
349 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000350 _sendREMB = true;
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000351 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
352 // throttled by the caller.
353 _nextTimeToSendRTCP = _clock->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000354 return 0;
355}
356
357bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000358RTCPSender::TMMBR() const
359{
360 CriticalSectionScoped lock(_criticalSectionRTCPSender);
361 return _TMMBR;
362}
363
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000364int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000365RTCPSender::SetTMMBRStatus(const bool enable)
366{
367 CriticalSectionScoped lock(_criticalSectionRTCPSender);
368 _TMMBR = enable;
369 return 0;
370}
371
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000372bool
373RTCPSender::IJ() const
374{
375 CriticalSectionScoped lock(_criticalSectionRTCPSender);
376 return _IJ;
377}
378
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000379int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000380RTCPSender::SetIJStatus(const bool enable)
381{
382 CriticalSectionScoped lock(_criticalSectionRTCPSender);
383 _IJ = enable;
384 return 0;
385}
386
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000387void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
388 start_timestamp_ = start_timestamp;
389}
390
391void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
392 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000393 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000394 last_rtp_timestamp_ = rtp_timestamp;
395 if (capture_time_ms < 0) {
396 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000397 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000398 } else {
399 last_frame_capture_time_ms_ = capture_time_ms;
400 }
401}
402
niklase@google.com470e71d2011-07-07 08:21:25 +0000403void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000404RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000405{
406 CriticalSectionScoped lock(_criticalSectionRTCPSender);
407
408 if(_SSRC != 0)
409 {
410 // not first SetSSRC, probably due to a collision
411 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000412 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000413 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000414 }
415 _SSRC = ssrc;
416}
417
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000418void RTCPSender::SetRemoteSSRC(uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000419{
420 CriticalSectionScoped lock(_criticalSectionRTCPSender);
421 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000422}
423
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000424int32_t
425RTCPSender::SetCameraDelay(const int32_t delayMS)
426{
427 CriticalSectionScoped lock(_criticalSectionRTCPSender);
428 if(delayMS > 1000 || delayMS < -1000)
429 {
430 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
431 return -1;
432 }
433 _cameraDelayMS = delayMS;
434 return 0;
435}
436
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000437int32_t RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000438 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000439 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000440 cName[RTCP_CNAME_SIZE - 1] = 0;
441 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000442 return 0;
443}
444
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000445int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000446 if (!cName)
447 return -1;
448
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000449 CriticalSectionScoped lock(_criticalSectionRTCPSender);
450 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
451 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
452 return 0;
453}
454
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000455int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
456 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000457 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000458 CriticalSectionScoped lock(_criticalSectionRTCPSender);
459 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
460 return -1;
461 }
462 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000463 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
464 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000465 _csrcCNAMEs[SSRC] = ptr;
466 return 0;
467}
468
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000469int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000470 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000471 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000472 _csrcCNAMEs.find(SSRC);
473
474 if (it == _csrcCNAMEs.end()) {
475 return -1;
476 }
477 delete it->second;
478 _csrcCNAMEs.erase(it);
479 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000480}
481
482bool
483RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
484{
485/*
486 For audio we use a fix 5 sec interval
487
488 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000489 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
490 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000491
492
493From RFC 3550
494
495 MAX RTCP BW is 5% if the session BW
496 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000497 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000498
499 The RECOMMENDED value for the reduced minimum in seconds is 360
500 divided by the session bandwidth in kilobits/second. This minimum
501 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
502
503 If the participant has not yet sent an RTCP packet (the variable
504 initial is true), the constant Tmin is set to 2.5 seconds, else it
505 is set to 5 seconds.
506
507 The interval between RTCP packets is varied randomly over the
508 range [0.5,1.5] times the calculated interval to avoid unintended
509 synchronization of all participants
510
511 if we send
512 If the participant is a sender (we_sent true), the constant C is
513 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
514 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
515 number of senders.
516
517 if we receive only
518 If we_sent is not true, the constant C is set
519 to the average RTCP packet size divided by 75% of the RTCP
520 bandwidth. The constant n is set to the number of receivers
521 (members - senders). If the number of senders is greater than
522 25%, senders and receivers are treated together.
523
524 reconsideration NOT required for peer-to-peer
525 "timer reconsideration" is
526 employed. This algorithm implements a simple back-off mechanism
527 which causes users to hold back RTCP packet transmission if the
528 group sizes are increasing.
529
530 n = number of members
531 C = avg_size/(rtcpBW/4)
532
533 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
534
535 4. The calculated interval T is set to a number uniformly distributed
536 between 0.5 and 1.5 times the deterministic calculated interval.
537
538 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
539 for the fact that the timer reconsideration algorithm converges to
540 a value of the RTCP bandwidth below the intended average
541*/
542
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000543 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000544
545 CriticalSectionScoped lock(_criticalSectionRTCPSender);
546
niklase@google.com470e71d2011-07-07 08:21:25 +0000547 if(_method == kRtcpOff)
548 {
549 return false;
550 }
551
niklase@google.com470e71d2011-07-07 08:21:25 +0000552 if(!_audio && sendKeyframeBeforeRTP)
553 {
554 // for video key-frames we want to send the RTCP before the large key-frame
555 // if we have a 100 ms margin
556 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
557 }
558
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000559 if(now >= _nextTimeToSendRTCP)
niklase@google.com470e71d2011-07-07 08:21:25 +0000560 {
561 return true;
562
563 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
564 {
565 // wrap
566 return true;
567 }
568 return false;
569}
570
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000571uint32_t
572RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000573{
574 CriticalSectionScoped lock(_criticalSectionRTCPSender);
575
576 lastRTCPTime = _lastRTCPTime[0];
577 return _lastSendReport[0];
578}
579
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000580uint32_t
581RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000582{
583 CriticalSectionScoped lock(_criticalSectionRTCPSender);
584
585 // This is only saved when we are the sender
586 if((_lastSendReport[0] == 0) || (sendReport == 0))
587 {
588 return 0; // will be ignored
589 } else
590 {
591 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
592 {
593 if( _lastSendReport[i] == sendReport)
594 {
595 return _lastRTCPTime[i];
596 }
597 }
598 }
599 return 0;
600}
601
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000602bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
603 int64_t* time_ms) const {
604 CriticalSectionScoped lock(_criticalSectionRTCPSender);
605
606 if (last_xr_rr_.empty()) {
607 return false;
608 }
609 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
610 if (it == last_xr_rr_.end()) {
611 return false;
612 }
613 *time_ms = it->second;
614 return true;
615}
616
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000617void RTCPSender::GetPacketTypeCounter(
618 RtcpPacketTypeCounter* packet_counter) const {
619 CriticalSectionScoped lock(_criticalSectionRTCPSender);
620 *packet_counter = packet_type_counter_;
621}
622
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000623int32_t RTCPSender::AddExternalReportBlock(
624 uint32_t SSRC,
625 const RTCPReportBlock* reportBlock) {
626 CriticalSectionScoped lock(_criticalSectionRTCPSender);
627 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
628}
629
630int32_t RTCPSender::AddReportBlock(
631 uint32_t SSRC,
632 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
633 const RTCPReportBlock* reportBlock) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000634 if (reportBlock == NULL) {
635 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
636 "%s invalid argument", __FUNCTION__);
637 return -1;
638 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000639
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000640 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000641 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
642 "%s invalid argument", __FUNCTION__);
643 return -1;
644 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000645 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000646 report_blocks->find(SSRC);
647 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000648 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000649 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000650 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000651 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
652 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000653 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000654 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000655}
656
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000657int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000658 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000659
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000660 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000661 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000662
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000663 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000664 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000665 }
666 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000667 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000668 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000669}
670
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000671int32_t RTCPSender::BuildSR(const FeedbackState& feedback_state,
672 uint8_t* rtcpbuffer,
673 int& pos,
674 uint32_t NTPsec,
675 uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000676{
677 // sanity
678 if(pos + 52 >= IP_PACKET_SIZE)
679 {
680 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
681 return -2;
682 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000683 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000684
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000685 uint32_t posNumberOfReportBlocks = pos;
686 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000687
688 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000689 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000690
691 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
692 {
693 // shift old
694 _lastSendReport[i+1] = _lastSendReport[i];
695 _lastRTCPTime[i+1] =_lastRTCPTime[i];
696 }
697
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000698 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000699 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000700
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000701 // The timestamp of this RTCP packet should be estimated as the timestamp of
702 // the frame being captured at this moment. We are calculating that
703 // timestamp as the last frame's timestamp + the time since the last frame
704 // was captured.
705 {
706 // Needs protection since this method is called on the process thread.
707 CriticalSectionScoped lock(_criticalSectionRTCPSender);
708 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
709 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000710 (feedback_state.frequency_hz / 1000);
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000711 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000712
713 // Add sender data
714 // Save for our length field
715 pos++;
716 pos++;
717
718 // Add our own SSRC
719 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
720 pos += 4;
721 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000722 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000723 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000724 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000725 pos += 4;
726 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
727 pos += 4;
728
729 //sender's packet count
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000730 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
731 feedback_state.packet_count_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000732 pos += 4;
733
734 //sender's octet count
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000735 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
736 feedback_state.byte_count_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000737 pos += 4;
738
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000739 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000740 int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
741 numberOfReportBlocks,
742 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000743 if(retVal < 0)
744 {
745 //
746 return retVal ;
747 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000748 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000749 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
750
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000751 uint16_t len = uint16_t((pos/4) -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000752 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
753 return 0;
754}
755
756
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000757int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000758 size_t lengthCname = strlen(_CNAME);
759 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000760
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000761 // sanity
762 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
763 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
764 "%s invalid argument", __FUNCTION__);
765 return -2;
766 }
767 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000768
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000769 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000770 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
771 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000772
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000773 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000774 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000775 pos++;
776 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000777
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000778 // Add our own SSRC
779 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
780 pos += 4;
781
782 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000783 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000784
785 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000786 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000787
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000788 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000789
790 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
791 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000792 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000793
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000794 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000795 // We must have a zero field even if we have an even multiple of 4 bytes
796 if ((pos % 4) == 0) {
797 padding++;
798 rtcpbuffer[pos++]=0;
799 }
800 while ((pos % 4) != 0) {
801 padding++;
802 rtcpbuffer[pos++]=0;
803 }
804 SDESLength += padding;
805
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000806 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000807 _csrcCNAMEs.begin();
808
809 for(; it != _csrcCNAMEs.end(); it++) {
810 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000811 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000812
813 // Add SSRC
814 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000815 pos += 4;
816
817 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000818 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000819
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000820 size_t length = strlen(cname->name);
821 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000822
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000823 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000824 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000825
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000826 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000827
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000828 pos += length;
829 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000830 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000831
832 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000833 if((pos % 4) == 0){
834 padding++;
835 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000836 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000837 while((pos % 4) != 0){
838 padding++;
839 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000840 }
841 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000842 }
843 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000844 uint16_t buffer_length = (SDESLength / 4) - 1;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000845 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
846 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000847 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000848}
849
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000850int32_t
851RTCPSender::BuildRR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000852 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000853 const uint32_t NTPsec,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000854 const uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000855{
856 // sanity one block
857 if(pos + 32 >= IP_PACKET_SIZE)
858 {
859 return -2;
860 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000861 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000862
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000863 rtcpbuffer[pos++]=(uint8_t)0x80;
864 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000865
866 // Save for our length field
867 pos++;
868 pos++;
869
870 // Add our own SSRC
871 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
872 pos += 4;
873
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000874 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000875 int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
876 numberOfReportBlocks,
877 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000878 if(retVal < 0)
879 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000880 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000881 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000882 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000883 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
884
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000885 uint16_t len = uint16_t((pos)/4 -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000886 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
887 return 0;
888}
889
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000890// From RFC 5450: Transmission Time Offsets in RTP Streams.
891// 0 1 2 3
892// 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
893// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
894// hdr |V=2|P| RC | PT=IJ=195 | length |
895// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
896// | inter-arrival jitter |
897// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
898// . .
899// . .
900// . .
901// | inter-arrival jitter |
902// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
903//
904// If present, this RTCP packet must be placed after a receiver report
905// (inside a compound RTCP packet), and MUST have the same value for RC
906// (reception report count) as the receiver report.
907
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000908int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000909RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000910 uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000911 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000912 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000913{
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000914 if (external_report_blocks_.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000915 {
916 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
917 return 0;
918 }
919
920 // sanity
921 if(pos + 8 >= IP_PACKET_SIZE)
922 {
923 return -2;
924 }
925 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000926 uint8_t RC = 1;
927 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
928 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000929
930 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000931 rtcpbuffer[pos++]=(uint8_t)0;
932 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000933
934 // Add inter-arrival jitter
935 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
936 jitterTransmissionTimeOffset);
937 pos += 4;
938 return 0;
939}
940
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000941int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000942RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000943{
944 // sanity
945 if(pos + 12 >= IP_PACKET_SIZE)
946 {
947 return -2;
948 }
949 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000950 uint8_t FMT = 1;
951 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
952 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000953
954 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000955 rtcpbuffer[pos++]=(uint8_t)0;
956 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000957
958 // Add our own SSRC
959 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
960 pos += 4;
961
962 // Add the remote SSRC
963 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
964 pos += 4;
965 return 0;
966}
967
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000968int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000969 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000970 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000971 // sanity
972 if(pos + 20 >= IP_PACKET_SIZE) {
973 return -2;
974 }
975 if (!repeat) {
976 _sequenceNumberFIR++; // do not increase if repetition
977 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000978
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000979 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000980 uint8_t FMT = 4;
981 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
982 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000983
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000984 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000985 rtcpbuffer[pos++] = (uint8_t)0;
986 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000987
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000988 // Add our own SSRC
989 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
990 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000991
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000992 // RFC 5104 4.3.1.2. Semantics
993 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000994 rtcpbuffer[pos++] = (uint8_t)0;
995 rtcpbuffer[pos++] = (uint8_t)0;
996 rtcpbuffer[pos++] = (uint8_t)0;
997 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000998
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000999 // Additional Feedback Control Information (FCI)
1000 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
1001 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001002
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001003 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
1004 rtcpbuffer[pos++] = (uint8_t)0;
1005 rtcpbuffer[pos++] = (uint8_t)0;
1006 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001007 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001008}
1009
1010/*
1011 0 1 2 3
1012 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
1013 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1014 | First | Number | PictureID |
1015 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1016*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001017int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001018RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +00001019{
1020 // sanity
1021 if(pos + 16 >= IP_PACKET_SIZE)
1022 {
1023 return -2;
1024 }
1025 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001026 uint8_t FMT = 2;
1027 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1028 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001029
1030 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001031 rtcpbuffer[pos++]=(uint8_t)0;
1032 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +00001033
1034 // Add our own SSRC
1035 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1036 pos += 4;
1037
1038 // Add the remote SSRC
1039 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1040 pos += 4;
1041
1042 // Add first, number & picture ID 6 bits
1043 // first = 0, 13 - bits
1044 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001045 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +00001046 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
1047 pos += 4;
1048 return 0;
1049}
1050
1051/*
1052 0 1 2 3
1053 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
1054 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1055 | PB |0| Payload Type| Native RPSI bit string |
1056 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1057 | defined per codec ... | Padding (0) |
1058 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1059*/
1060/*
1061* Note: not generic made for VP8
1062*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001063int32_t
1064RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001065 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001066 const uint64_t pictureID,
1067 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +00001068{
1069 // sanity
1070 if(pos + 24 >= IP_PACKET_SIZE)
1071 {
1072 return -2;
1073 }
1074 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001075 uint8_t FMT = 3;
1076 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1077 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001078
1079 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001080 uint32_t bitsRequired = 7;
1081 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001082 while((pictureID>>bitsRequired) > 0)
1083 {
1084 bitsRequired += 7;
1085 bytesRequired++;
1086 }
1087
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001088 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001089 if(bytesRequired > 6)
1090 {
1091 size = 5;
1092 } else if(bytesRequired > 2)
1093 {
1094 size = 4;
1095 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001096 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001097 rtcpbuffer[pos++]=size;
1098
1099 // Add our own SSRC
1100 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1101 pos += 4;
1102
1103 // Add the remote SSRC
1104 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1105 pos += 4;
1106
1107 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001108 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001109 if(paddingBytes == 4)
1110 {
1111 paddingBytes = 0;
1112 }
1113 // add padding length in bits
1114 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1115 pos++;
1116
1117 // add payload type
1118 rtcpbuffer[pos] = payloadType;
1119 pos++;
1120
1121 // add picture ID
1122 for(int i = bytesRequired-1; i > 0; i--)
1123 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001124 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001125 pos++;
1126 }
1127 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001128 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001129 pos++;
1130
1131 // add padding
1132 for(int j = 0; j <paddingBytes; j++)
1133 {
1134 rtcpbuffer[pos] = 0;
1135 pos++;
1136 }
1137 return 0;
1138}
1139
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001140int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001141RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001142{
1143 // sanity
1144 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1145 {
1146 return -2;
1147 }
1148 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001149 uint8_t FMT = 15;
1150 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1151 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001152
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001153 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001154 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1155
1156 // Add our own SSRC
1157 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1158 pos += 4;
1159
1160 // Remote SSRC must be 0
1161 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1162 pos += 4;
1163
1164 rtcpbuffer[pos++]='R';
1165 rtcpbuffer[pos++]='E';
1166 rtcpbuffer[pos++]='M';
1167 rtcpbuffer[pos++]='B';
1168
1169 rtcpbuffer[pos++] = _lengthRembSSRC;
1170 // 6 bit Exp
1171 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001172 uint8_t brExp = 0;
1173 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001174 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001175 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001176 {
1177 brExp = i;
1178 break;
1179 }
1180 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001181 const uint32_t brMantissa = (_rembBitrate >> brExp);
1182 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1183 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1184 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001185
1186 for (int i = 0; i < _lengthRembSSRC; i++)
1187 {
1188 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1189 pos += 4;
1190 }
1191 return 0;
1192}
1193
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001194void
1195RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001196{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001197 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001198 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001199}
1200
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001201int32_t RTCPSender::BuildTMMBR(ModuleRtpRtcpImpl* rtp_rtcp_module,
1202 uint8_t* rtcpbuffer,
1203 int& pos) {
1204 if (rtp_rtcp_module == NULL)
1205 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001206 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1207 // If the sender is an owner of the TMMBN -> send TMMBR
1208 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1209
niklase@google.com470e71d2011-07-07 08:21:25 +00001210 // get current bounding set from RTCP receiver
1211 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001212 // store in candidateSet, allocates one extra slot
1213 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001214
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001215 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1216 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1217 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001218 int32_t lengthOfBoundingSet =
1219 rtp_rtcp_module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001220
1221 if(lengthOfBoundingSet > 0)
1222 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001223 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001224 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001225 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1226 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001227 {
1228 // do not send the same tuple
1229 return 0;
1230 }
1231 }
1232 if(!tmmbrOwner)
1233 {
1234 // use received bounding set as candidate set
1235 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001236 candidateSet->SetEntry(lengthOfBoundingSet,
1237 _tmmbr_Send,
1238 _packetOH_Send,
1239 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001240 int numCandidates = lengthOfBoundingSet+ 1;
1241
1242 // find bounding set
1243 TMMBRSet* boundingSet = NULL;
1244 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1245 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1246 {
1247 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1248 }
1249 if(!tmmbrOwner)
1250 {
1251 // did not enter bounding set, no meaning to send this request
1252 return 0;
1253 }
1254 }
1255 }
1256
1257 if(_tmmbr_Send)
1258 {
1259 // sanity
1260 if(pos + 20 >= IP_PACKET_SIZE)
1261 {
1262 return -2;
1263 }
1264 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001265 uint8_t FMT = 3;
1266 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1267 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001268
1269 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001270 rtcpbuffer[pos++]=(uint8_t)0;
1271 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001272
1273 // Add our own SSRC
1274 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1275 pos += 4;
1276
1277 // RFC 5104 4.2.1.2. Semantics
1278
1279 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001280 rtcpbuffer[pos++]=(uint8_t)0;
1281 rtcpbuffer[pos++]=(uint8_t)0;
1282 rtcpbuffer[pos++]=(uint8_t)0;
1283 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001284
1285 // Additional Feedback Control Information (FCI)
1286 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1287 pos += 4;
1288
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001289 uint32_t bitRate = _tmmbr_Send*1000;
1290 uint32_t mmbrExp = 0;
1291 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001292 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001293 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001294 {
1295 mmbrExp = i;
1296 break;
1297 }
1298 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001299 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001300
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001301 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1302 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1303 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1304 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001305 }
1306 return 0;
1307}
1308
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001309int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001310RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001311{
1312 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1313 if(boundingSet == NULL)
1314 {
1315 return -1;
1316 }
1317 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001318 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001319 {
1320 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1321 return -2;
1322 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001323 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001324 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001325 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1326 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001327
1328 //Add length later
1329 int posLength = pos;
1330 pos++;
1331 pos++;
1332
1333 // Add our own SSRC
1334 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1335 pos += 4;
1336
1337 // RFC 5104 4.2.2.2. Semantics
1338
1339 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001340 rtcpbuffer[pos++]=(uint8_t)0;
1341 rtcpbuffer[pos++]=(uint8_t)0;
1342 rtcpbuffer[pos++]=(uint8_t)0;
1343 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001344
1345 // Additional Feedback Control Information (FCI)
1346 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001347 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001348 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001349 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001350 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001351 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001352 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1353 pos += 4;
1354
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001355 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1356 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001357 for(int i=0; i<64; i++)
1358 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001359 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001360 {
1361 mmbrExp = i;
1362 break;
1363 }
1364 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001365 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1366 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001367
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001368 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1369 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1370 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1371 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001372 numBoundingSet++;
1373 }
1374 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001375 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1376 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1377 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001378 return 0;
1379}
1380
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001381int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001382RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001383{
1384 // sanity
1385 if(_appData == NULL)
1386 {
1387 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1388 return -1;
1389 }
1390 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1391 {
1392 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1393 return -2;
1394 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001395 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001396
1397 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001398 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001399
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001400 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1401 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1402 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001403
1404 // Add our own SSRC
1405 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1406 pos += 4;
1407
1408 // Add our application name
1409 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1410 pos += 4;
1411
1412 // Add the data
1413 memcpy(rtcpbuffer +pos, _appData,_appLength);
1414 pos += _appLength;
1415 return 0;
1416}
1417
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001418int32_t
1419RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001420 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001421 const int32_t nackSize,
1422 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001423 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001424{
1425 // sanity
1426 if(pos + 16 >= IP_PACKET_SIZE)
1427 {
1428 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1429 return -2;
1430 }
1431
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001432 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001433 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001434 uint8_t FMT = 1;
1435 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1436 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001437
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001438 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001439 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001440 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001441
1442 // Add our own SSRC
1443 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1444 pos += 4;
1445
1446 // Add the remote SSRC
1447 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1448 pos += 4;
1449
edjee@google.com79b02892013-04-04 19:43:34 +00001450 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001451 // Build NACK bitmasks and write them to the RTCP message.
1452 // The nack list should be sorted and not contain duplicates if one
1453 // wants to build the smallest rtcp nack packet.
1454 int numOfNackFields = 0;
1455 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1456 (IP_PACKET_SIZE - pos) / 4);
1457 int i = 0;
1458 while (i < nackSize && numOfNackFields < maxNackFields) {
1459 stringBuilder.PushNACK(nackList[i]);
1460 uint16_t nack = nackList[i++];
1461 uint16_t bitmask = 0;
1462 while (i < nackSize) {
1463 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1464 if (shift >= 0 && shift <= 15) {
1465 stringBuilder.PushNACK(nackList[i]);
1466 bitmask |= (1 << shift);
1467 ++i;
1468 } else {
1469 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001470 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001471 }
1472 // Write the sequence number and the bitmask to the packet.
1473 assert(pos + 4 < IP_PACKET_SIZE);
1474 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
1475 pos += 2;
1476 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
1477 pos += 2;
1478 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001479 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001480 if (i != nackSize) {
1481 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1482 "Nack list to large for one packet.");
1483 }
1484 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001485 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001486 return 0;
1487}
1488
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001489int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001490RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001491{
1492 // sanity
1493 if(pos + 8 >= IP_PACKET_SIZE)
1494 {
1495 return -2;
1496 }
1497 if(_includeCSRCs)
1498 {
1499 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001500 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1501 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001502
1503 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001504 rtcpbuffer[pos++]=(uint8_t)0;
1505 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001506
1507 // Add our own SSRC
1508 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1509 pos += 4;
1510
1511 // add CSRCs
1512 for(int i = 0; i < _CSRCs; i++)
1513 {
1514 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1515 pos += 4;
1516 }
1517 } else
1518 {
1519 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001520 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1521 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001522
1523 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001524 rtcpbuffer[pos++]=(uint8_t)0;
1525 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001526
1527 // Add our own SSRC
1528 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1529 pos += 4;
1530 }
1531 return 0;
1532}
1533
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001534int32_t RTCPSender::BuildReceiverReferenceTime(uint8_t* buffer,
1535 int& pos,
1536 uint32_t ntp_sec,
1537 uint32_t ntp_frac) {
1538 const int kRrTimeBlockLength = 20;
1539 if (pos + kRrTimeBlockLength >= IP_PACKET_SIZE) {
1540 return -2;
1541 }
1542
1543 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) {
1544 last_xr_rr_.erase(last_xr_rr_.begin());
1545 }
1546 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
1547 RTCPUtility::MidNtp(ntp_sec, ntp_frac),
1548 Clock::NtpToMs(ntp_sec, ntp_frac)));
1549
1550 // Add XR header.
1551 buffer[pos++] = 0x80;
1552 buffer[pos++] = 207;
1553 buffer[pos++] = 0; // XR packet length.
1554 buffer[pos++] = 4; // XR packet length.
1555
1556 // Add our own SSRC.
1557 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
1558 pos += 4;
1559
1560 // 0 1 2 3
1561 // 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
1562 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1563 // | BT=4 | reserved | block length = 2 |
1564 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1565 // | NTP timestamp, most significant word |
1566 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1567 // | NTP timestamp, least significant word |
1568 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1569
1570 // Add Receiver Reference Time Report block.
1571 buffer[pos++] = 4; // BT.
1572 buffer[pos++] = 0; // Reserved.
1573 buffer[pos++] = 0; // Block length.
1574 buffer[pos++] = 2; // Block length.
1575
1576 // NTP timestamp.
1577 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, ntp_sec);
1578 pos += 4;
1579 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, ntp_frac);
1580 pos += 4;
1581
1582 return 0;
1583}
1584
1585int32_t RTCPSender::BuildDlrr(uint8_t* buffer,
1586 int& pos,
1587 const RtcpReceiveTimeInfo& info) {
1588 const int kDlrrBlockLength = 24;
1589 if (pos + kDlrrBlockLength >= IP_PACKET_SIZE) {
1590 return -2;
1591 }
1592
1593 // Add XR header.
1594 buffer[pos++] = 0x80;
1595 buffer[pos++] = 207;
1596 buffer[pos++] = 0; // XR packet length.
1597 buffer[pos++] = 5; // XR packet length.
1598
1599 // Add our own SSRC.
1600 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
1601 pos += 4;
1602
1603 // 0 1 2 3
1604 // 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
1605 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1606 // | BT=5 | reserved | block length |
1607 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1608 // | SSRC_1 (SSRC of first receiver) | sub-
1609 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1610 // | last RR (LRR) | 1
1611 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1612 // | delay since last RR (DLRR) |
1613 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1614 // | SSRC_2 (SSRC of second receiver) | sub-
1615 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1616 // : ... : 2
1617
1618 // Add DLRR sub block.
1619 buffer[pos++] = 5; // BT.
1620 buffer[pos++] = 0; // Reserved.
1621 buffer[pos++] = 0; // Block length.
1622 buffer[pos++] = 3; // Block length.
1623
1624 // NTP timestamp.
1625 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, info.sourceSSRC);
1626 pos += 4;
1627 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, info.lastRR);
1628 pos += 4;
1629 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, info.delaySinceLastRR);
1630 pos += 4;
1631
1632 return 0;
1633}
1634
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001635int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001636RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001637{
1638 // sanity
1639 if(pos + 44 >= IP_PACKET_SIZE)
1640 {
1641 return -2;
1642 }
1643
1644 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001645 rtcpbuffer[pos++]=(uint8_t)0x80;
1646 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001647
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001648 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001649
1650 // handle length later on
1651 pos++;
1652 pos++;
1653
1654 // Add our own SSRC
1655 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1656 pos += 4;
1657
1658 // Add a VoIP metrics block
1659 rtcpbuffer[pos++]=7;
1660 rtcpbuffer[pos++]=0;
1661 rtcpbuffer[pos++]=0;
1662 rtcpbuffer[pos++]=8;
1663
1664 // Add the remote SSRC
1665 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1666 pos += 4;
1667
1668 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1669 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1670 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1671 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1672
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001673 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1674 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1675 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1676 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001677
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001678 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1679 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1680 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1681 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001682
1683 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1684 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1685 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1686 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1687
1688 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1689 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1690 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1691 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1692
1693 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1694 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001695 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1696 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001697
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001698 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1699 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1700 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1701 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001702
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001703 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1704 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001705 return 0;
1706}
1707
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001708int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
1709 uint32_t packetTypeFlags,
1710 int32_t nackSize,
1711 const uint16_t* nackList,
1712 bool repeat,
1713 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001714 {
1715 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1716 if(_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001717 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001718 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1719 "%s invalid state", __FUNCTION__);
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001720 return -1;
1721 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001722 }
1723 uint8_t rtcp_buffer[IP_PACKET_SIZE];
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001724 int rtcp_length = PrepareRTCP(feedback_state,
1725 packetTypeFlags,
1726 nackSize,
1727 nackList,
1728 repeat,
1729 pictureID,
1730 rtcp_buffer,
1731 IP_PACKET_SIZE);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001732 if (rtcp_length < 0) {
1733 return -1;
1734 }
1735 // Sanity don't send empty packets.
1736 if (rtcp_length == 0)
1737 {
1738 return -1;
1739 }
1740 return SendToNetwork(rtcp_buffer, static_cast<uint16_t>(rtcp_length));
1741}
1742
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001743int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
1744 uint32_t packetTypeFlags,
1745 int32_t nackSize,
1746 const uint16_t* nackList,
1747 bool repeat,
1748 uint64_t pictureID,
1749 uint8_t* rtcp_buffer,
1750 int buffer_size) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001751 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1752 // Collect the received information.
1753 uint32_t NTPsec = 0;
1754 uint32_t NTPfrac = 0;
1755 uint32_t jitterTransmissionOffset = 0;
1756 int position = 0;
1757
1758 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1759
1760 if(_TMMBR ) // Attach TMMBR to send and receive reports.
1761 {
1762 rtcpPacketTypeFlags |= kRtcpTmmbr;
1763 }
1764 if(_appSend)
1765 {
1766 rtcpPacketTypeFlags |= kRtcpApp;
1767 _appSend = false;
1768 }
1769 if(_REMB && _sendREMB)
1770 {
1771 // Always attach REMB to SR if that is configured. Note that REMB is
1772 // only sent on one of the RTP modules in the REMB group.
1773 rtcpPacketTypeFlags |= kRtcpRemb;
1774 }
1775 if(_xrSendVoIPMetric)
1776 {
1777 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1778 _xrSendVoIPMetric = false;
1779 }
1780 if(_sendTMMBN) // Set when having received a TMMBR.
1781 {
1782 rtcpPacketTypeFlags |= kRtcpTmmbn;
1783 _sendTMMBN = false;
1784 }
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001785 if (rtcpPacketTypeFlags & kRtcpReport)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001786 {
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001787 if (xrSendReceiverReferenceTimeEnabled_ && !_sending)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001788 {
1789 rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
1790 }
1791 if (feedback_state.has_last_xr_rr)
1792 {
1793 rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
1794 }
1795 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001796 if(_method == kRtcpCompound)
1797 {
1798 if(_sending)
1799 {
1800 rtcpPacketTypeFlags |= kRtcpSr;
1801 } else
1802 {
1803 rtcpPacketTypeFlags |= kRtcpRr;
1804 }
1805 } else if(_method == kRtcpNonCompound)
1806 {
1807 if(rtcpPacketTypeFlags & kRtcpReport)
1808 {
1809 if(_sending)
1810 {
1811 rtcpPacketTypeFlags |= kRtcpSr;
1812 } else
1813 {
1814 rtcpPacketTypeFlags |= kRtcpRr;
1815 }
1816 }
1817 }
1818 if( rtcpPacketTypeFlags & kRtcpRr ||
1819 rtcpPacketTypeFlags & kRtcpSr)
1820 {
1821 // generate next time to send a RTCP report
1822 // seeded from RTP constructor
1823 int32_t random = rand() % 1000;
1824 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1825
1826 if(_audio)
1827 {
1828 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1829 (RTCP_INTERVAL_AUDIO_MS*random/1000);
1830 }else
1831 {
1832 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1833 if(_sending)
1834 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001835 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1836 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1837 if (send_bitrate_kbit != 0)
1838 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001839 }
1840 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1841 {
1842 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1843 }
1844 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1845 }
1846 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1847 }
1848
1849 // If the data does not fit in the packet we fill it as much as possible.
1850 int32_t buildVal = 0;
1851
1852 // We need to send our NTP even if we haven't received any reports.
1853 _clock->CurrentNtp(NTPsec, NTPfrac);
1854 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1855 StatisticianMap statisticians =
1856 receive_statistics_->GetActiveStatisticians();
1857 if (!statisticians.empty()) {
1858 StatisticianMap::const_iterator it;
1859 int i;
1860 for (it = statisticians.begin(), i = 0; it != statisticians.end();
1861 ++it, ++i) {
1862 RTCPReportBlock report_block;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001863 if (PrepareReport(
1864 feedback_state, it->second, &report_block, &NTPsec, &NTPfrac))
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001865 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1866 }
1867 if (_IJ && !statisticians.empty()) {
1868 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1869 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001870 }
1871 }
1872
1873 if(rtcpPacketTypeFlags & kRtcpSr)
1874 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001875 buildVal = BuildSR(feedback_state, rtcp_buffer, position, NTPsec, NTPfrac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001876 if (buildVal == -1) {
1877 return -1;
1878 } else if (buildVal == -2) {
1879 return position;
1880 }
1881 buildVal = BuildSDEC(rtcp_buffer, position);
1882 if (buildVal == -1) {
1883 return -1;
1884 } else if (buildVal == -2) {
1885 return position;
1886 }
1887 }else if(rtcpPacketTypeFlags & kRtcpRr)
1888 {
1889 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1890 if (buildVal == -1) {
1891 return -1;
1892 } else if (buildVal == -2) {
1893 return position;
1894 }
1895 // only of set
1896 if(_CNAME[0] != 0)
1897 {
1898 buildVal = BuildSDEC(rtcp_buffer, position);
1899 if (buildVal == -1) {
1900 return -1;
1901 }
1902 }
1903 }
1904 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1905 {
1906 // If present, this RTCP packet must be placed after a
1907 // receiver report.
1908 buildVal = BuildExtendedJitterReport(rtcp_buffer,
1909 position,
1910 jitterTransmissionOffset);
1911 if (buildVal == -1) {
1912 return -1;
1913 } else if (buildVal == -2) {
1914 return position;
1915 }
1916 }
1917 if(rtcpPacketTypeFlags & kRtcpPli)
1918 {
1919 buildVal = BuildPLI(rtcp_buffer, position);
1920 if (buildVal == -1) {
1921 return -1;
1922 } else if (buildVal == -2) {
1923 return position;
1924 }
1925 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001926 ++packet_type_counter_.pli_packets;
1927 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC,
1928 packet_type_counter_.pli_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001929 }
1930 if(rtcpPacketTypeFlags & kRtcpFir)
1931 {
1932 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1933 if (buildVal == -1) {
1934 return -1;
1935 } else if (buildVal == -2) {
1936 return position;
1937 }
1938 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001939 ++packet_type_counter_.fir_packets;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001940 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001941 packet_type_counter_.fir_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001942 }
1943 if(rtcpPacketTypeFlags & kRtcpSli)
1944 {
1945 buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1946 if (buildVal == -1) {
1947 return -1;
1948 } else if (buildVal == -2) {
1949 return position;
1950 }
1951 }
1952 if(rtcpPacketTypeFlags & kRtcpRpsi)
1953 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001954 const int8_t payloadType = feedback_state.send_payload_type;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001955 if (payloadType == -1) {
1956 return -1;
1957 }
1958 buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1959 (uint8_t)payloadType);
1960 if (buildVal == -1) {
1961 return -1;
1962 } else if (buildVal == -2) {
1963 return position;
1964 }
1965 }
1966 if(rtcpPacketTypeFlags & kRtcpRemb)
1967 {
1968 buildVal = BuildREMB(rtcp_buffer, position);
1969 if (buildVal == -1) {
1970 return -1;
1971 } else if (buildVal == -2) {
1972 return position;
1973 }
1974 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1975 }
1976 if(rtcpPacketTypeFlags & kRtcpBye)
1977 {
1978 buildVal = BuildBYE(rtcp_buffer, position);
1979 if (buildVal == -1) {
1980 return -1;
1981 } else if (buildVal == -2) {
1982 return position;
1983 }
1984 }
1985 if(rtcpPacketTypeFlags & kRtcpApp)
1986 {
1987 buildVal = BuildAPP(rtcp_buffer, position);
1988 if (buildVal == -1) {
1989 return -1;
1990 } else if (buildVal == -2) {
1991 return position;
1992 }
1993 }
1994 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1995 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001996 buildVal = BuildTMMBR(feedback_state.module, rtcp_buffer, position);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001997 if (buildVal == -1) {
1998 return -1;
1999 } else if (buildVal == -2) {
2000 return position;
2001 }
2002 }
2003 if(rtcpPacketTypeFlags & kRtcpTmmbn)
2004 {
2005 buildVal = BuildTMMBN(rtcp_buffer, position);
2006 if (buildVal == -1) {
2007 return -1;
2008 } else if (buildVal == -2) {
2009 return position;
2010 }
2011 }
2012 if(rtcpPacketTypeFlags & kRtcpNack)
2013 {
2014 std::string nackString;
2015 buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
2016 &nackString);
2017 if (buildVal == -1) {
2018 return -1;
2019 } else if (buildVal == -2) {
2020 return position;
2021 }
2022 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
2023 "nacks", TRACE_STR_COPY(nackString.c_str()));
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00002024 ++packet_type_counter_.nack_packets;
2025 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC,
2026 packet_type_counter_.nack_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002027 }
2028 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
2029 {
2030 buildVal = BuildVoIPMetric(rtcp_buffer, position);
2031 if (buildVal == -1) {
2032 return -1;
2033 } else if (buildVal == -2) {
2034 return position;
2035 }
2036 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002037 if (rtcpPacketTypeFlags & kRtcpXrReceiverReferenceTime)
2038 {
2039 buildVal = BuildReceiverReferenceTime(rtcp_buffer,
2040 position,
2041 NTPsec,
2042 NTPfrac);
2043 if (buildVal == -1) {
2044 return -1;
2045 } else if (buildVal == -2) {
2046 return position;
2047 }
2048 }
2049 if (rtcpPacketTypeFlags & kRtcpXrDlrrReportBlock)
2050 {
2051 buildVal = BuildDlrr(rtcp_buffer, position, feedback_state.last_xr_rr);
2052 if (buildVal == -1) {
2053 return -1;
2054 } else if (buildVal == -2) {
2055 return position;
2056 }
2057 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002058 return position;
2059}
2060
2061bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
2062 return Status() == kRtcpCompound ||
2063 (rtcp_packet_type & kRtcpReport) ||
2064 (rtcp_packet_type & kRtcpSr) ||
2065 (rtcp_packet_type & kRtcpRr);
2066}
2067
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002068bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
2069 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002070 RTCPReportBlock* report_block,
2071 uint32_t* ntp_secs, uint32_t* ntp_frac) {
2072 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00002073 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002074 if (!statistician->GetStatistics(&stats, true))
2075 return false;
2076 report_block->fractionLost = stats.fraction_lost;
2077 report_block->cumulativeLost = stats.cumulative_lost;
2078 report_block->extendedHighSeqNum =
2079 stats.extended_max_sequence_number;
2080 report_block->jitter = stats.jitter;
2081
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002082 // get our NTP as late as possible to avoid a race
2083 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
2084
2085 // Delay since last received report
2086 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002087 if ((feedback_state.last_rr_ntp_secs != 0) ||
2088 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002089 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
2090 uint32_t now=*ntp_secs&0x0000FFFF;
2091 now <<=16;
2092 now += (*ntp_frac&0xffff0000)>>16;
2093
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002094 uint32_t receiveTime = feedback_state.last_rr_ntp_secs&0x0000FFFF;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002095 receiveTime <<=16;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002096 receiveTime += (feedback_state.last_rr_ntp_frac&0xffff0000)>>16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002097
2098 delaySinceLastReceivedSR = now-receiveTime;
2099 }
2100 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002101 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002102 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00002103}
2104
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002105int32_t
2106RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
2107 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002108{
2109 CriticalSectionScoped lock(_criticalSectionTransport);
2110 if(_cbTransport)
2111 {
2112 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
2113 {
2114 return 0;
2115 }
2116 }
2117 return -1;
2118}
2119
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002120int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002121RTCPSender::SetCSRCStatus(const bool include)
2122{
2123 _includeCSRCs = include;
2124 return 0;
2125}
2126
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002127int32_t
2128RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
2129 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00002130{
2131 if(arrLength > kRtpCsrcSize)
2132 {
2133 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2134 assert(false);
2135 return -1;
2136 }
2137
2138 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2139
2140 for(int i = 0; i < arrLength;i++)
2141 {
2142 _CSRC[i] = arrOfCSRC[i];
2143 }
2144 _CSRCs = arrLength;
2145 return 0;
2146}
2147
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002148int32_t
2149RTCPSender::SetApplicationSpecificData(const uint8_t subType,
2150 const uint32_t name,
2151 const uint8_t* data,
2152 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002153{
2154 if(length %4 != 0)
2155 {
2156 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2157 return -1;
2158 }
2159 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2160
2161 if(_appData)
2162 {
2163 delete [] _appData;
2164 }
2165
2166 _appSend = true;
2167 _appSubType = subType;
2168 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002169 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002170 _appLength = length;
2171 memcpy(_appData, data, length);
2172 return 0;
2173}
2174
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002175int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002176RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2177{
2178 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2179 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2180
2181 _xrSendVoIPMetric = true;
2182 return 0;
2183}
2184
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002185void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
2186 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2187 xrSendReceiverReferenceTimeEnabled_ = enable;
2188}
2189
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00002190bool RTCPSender::RtcpXrReceiverReferenceTime() const {
2191 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2192 return xrSendReceiverReferenceTimeEnabled_;
2193}
2194
niklase@google.com470e71d2011-07-07 08:21:25 +00002195// called under critsect _criticalSectionRTCPSender
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002196int32_t RTCPSender::WriteAllReportBlocksToBuffer(
2197 uint8_t* rtcpbuffer,
2198 int pos,
2199 uint8_t& numberOfReportBlocks,
2200 const uint32_t NTPsec,
2201 const uint32_t NTPfrac) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002202 // sanity one block
2203 if(pos + 24 >= IP_PACKET_SIZE) {
2204 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2205 "%s invalid argument", __FUNCTION__);
2206 return -1;
2207 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002208 numberOfReportBlocks = external_report_blocks_.size();
2209 numberOfReportBlocks += internal_report_blocks_.size();
2210 if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002211 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2212 "%s invalid argument", __FUNCTION__);
2213 return -1;
2214 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002215 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2216 while (!internal_report_blocks_.empty()) {
2217 delete internal_report_blocks_.begin()->second;
2218 internal_report_blocks_.erase(internal_report_blocks_.begin());
2219 }
2220 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2221 return pos;
2222}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002223
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002224int32_t RTCPSender::WriteReportBlocksToBuffer(
2225 uint8_t* rtcpbuffer,
2226 int32_t position,
2227 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2228 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2229 report_blocks.begin();
2230 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002231 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002232 RTCPReportBlock* reportBlock = it->second;
2233 if (reportBlock) {
2234 // Remote SSRC
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002235 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position, remoteSSRC);
2236 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002237
2238 // fraction lost
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002239 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002240
2241 // cumulative loss
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002242 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002243 reportBlock->cumulativeLost);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002244 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002245
2246 // extended highest seq_no, contain the highest sequence number received
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002247 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002248 reportBlock->extendedHighSeqNum);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002249 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002250
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002251 // Jitter
2252 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002253 reportBlock->jitter);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002254 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002255
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002256 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002257 reportBlock->lastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002258 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002259
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002260 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002261 reportBlock->delaySinceLastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002262 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002263 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002264 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002265 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00002266}
2267
2268// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002269int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002270RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002271 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002272{
2273 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2274
2275 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2276 {
2277 _sendTMMBN = true;
2278 return 0;
2279 }
2280 return -1;
2281}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002282} // namespace webrtc