blob: d73de9c42439e2f4733037f827faf83d09d573d9 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> // assert
14#include <stdlib.h> // rand
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000015#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000017#include <algorithm> // min
18
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000019#include "webrtc/common_types.h"
20#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
21#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000022#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000023#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000024
niklase@google.com470e71d2011-07-07 08:21:25 +000025namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000026
27using RTCPUtility::RTCPCnameInformation;
28
edjee@google.com79b02892013-04-04 19:43:34 +000029NACKStringBuilder::NACKStringBuilder() :
30 _stream(""), _count(0), _consecutive(false)
31{
32 // Empty.
33}
34
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000035NACKStringBuilder::~NACKStringBuilder() {}
36
pbos@webrtc.org2f446732013-04-08 11:08:41 +000037void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000038{
39 if (_count == 0)
40 {
41 _stream << nack;
42 } else if (nack == _prevNack + 1)
43 {
44 _consecutive = true;
45 } else
46 {
47 if (_consecutive)
48 {
49 _stream << "-" << _prevNack;
50 _consecutive = false;
51 }
52 _stream << "," << nack;
53 }
54 _count++;
55 _prevNack = nack;
56}
57
58std::string NACKStringBuilder::GetResult()
59{
60 if (_consecutive)
61 {
62 _stream << "-" << _prevNack;
63 _consecutive = false;
64 }
65 return _stream.str();
66}
67
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000068RTCPSender::FeedbackState::FeedbackState(ModuleRtpRtcpImpl* module)
69 : send_payload_type(module->SendPayloadType()),
70 frequency_hz(module->CurrentSendFrequencyHz()),
71 packet_count_sent(module->PacketCountSent()),
72 byte_count_sent(module->ByteCountSent()),
73 module(module) {
74 uint32_t last_ntp_secs = 0, last_ntp_frac = 0, last_remote_sr = 0;
75 module->LastReceivedNTP(last_ntp_secs, last_ntp_frac, last_remote_sr);
76 last_rr_ntp_secs = last_ntp_secs;
77 last_rr_ntp_frac = last_ntp_frac;
78 remote_sr = last_remote_sr;
79
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000080 has_last_xr_rr = module->LastReceivedXrReferenceTimeInfo(&last_xr_rr);
81
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000082 uint32_t send_bitrate = 0, tmp;
83 module->BitrateSent(&send_bitrate, &tmp, &tmp, &tmp);
84 this->send_bitrate = send_bitrate;
85}
86
87RTCPSender::FeedbackState::FeedbackState()
88 : send_payload_type(0),
89 frequency_hz(0),
90 packet_count_sent(0),
91 byte_count_sent(0),
92 send_bitrate(0),
93 last_rr_ntp_secs(0),
94 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000095 remote_sr(0),
96 has_last_xr_rr(false) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000097
pbos@webrtc.org2f446732013-04-08 11:08:41 +000098RTCPSender::RTCPSender(const int32_t id,
niklase@google.com470e71d2011-07-07 08:21:25 +000099 const bool audio,
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000100 Clock* clock,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000101 ReceiveStatistics* receive_statistics) :
niklase@google.com470e71d2011-07-07 08:21:25 +0000102 _id(id),
103 _audio(audio),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000104 _clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +0000105 _method(kRtcpOff),
henrike@webrtc.org65573f22011-12-13 19:17:27 +0000106 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +0000107 _cbTransport(NULL),
108
henrike@webrtc.org65573f22011-12-13 19:17:27 +0000109 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +0000110 _usingNack(false),
111 _sending(false),
112 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000113 _REMB(false),
114 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000115 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000116 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000117 _nextTimeToSendRTCP(0),
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000118 start_timestamp_(0),
119 last_rtp_timestamp_(0),
120 last_frame_capture_time_ms_(-1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000121 _SSRC(0),
122 _remoteSSRC(0),
123 _CNAME(),
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000124 receive_statistics_(receive_statistics),
125 internal_report_blocks_(),
126 external_report_blocks_(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000127 _csrcCNAMEs(),
128
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000129 _cameraDelayMS(0),
130
niklase@google.com470e71d2011-07-07 08:21:25 +0000131 _lastSendReport(),
132 _lastRTCPTime(),
133
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000134 last_xr_rr_(),
135
niklase@google.com470e71d2011-07-07 08:21:25 +0000136 _CSRCs(0),
137 _CSRC(),
138 _includeCSRCs(true),
139
140 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000141
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000142 _lengthRembSSRC(0),
143 _sizeRembSSRC(0),
144 _rembSSRC(NULL),
145 _rembBitrate(0),
146
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000147 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000148 _tmmbr_Send(0),
149 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000150
151 _appSend(false),
152 _appSubType(0),
153 _appName(),
154 _appData(NULL),
155 _appLength(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000156
157 xrSendReceiverReferenceTimeEnabled_(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000158 _xrSendVoIPMetric(false),
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000159 _xrVoIPMetric()
niklase@google.com470e71d2011-07-07 08:21:25 +0000160{
161 memset(_CNAME, 0, sizeof(_CNAME));
162 memset(_lastSendReport, 0, sizeof(_lastSendReport));
163 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
niklase@google.com470e71d2011-07-07 08:21:25 +0000164}
165
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000166RTCPSender::~RTCPSender() {
167 delete [] _rembSSRC;
168 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000169
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000170 while (!internal_report_blocks_.empty()) {
171 delete internal_report_blocks_.begin()->second;
172 internal_report_blocks_.erase(internal_report_blocks_.begin());
173 }
174 while (!external_report_blocks_.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000175 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000176 external_report_blocks_.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000177 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000178 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000179 }
180 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000181 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000182 _csrcCNAMEs.begin();
183 delete it->second;
184 _csrcCNAMEs.erase(it);
185 }
186 delete _criticalSectionTransport;
187 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000188}
189
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000190int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000191RTCPSender::Init()
192{
193 CriticalSectionScoped lock(_criticalSectionRTCPSender);
194
195 _method = kRtcpOff;
196 _cbTransport = NULL;
197 _usingNack = false;
198 _sending = false;
199 _sendTMMBN = false;
200 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000201 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000202 _REMB = false;
203 _sendREMB = false;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000204 last_rtp_timestamp_ = 0;
205 last_frame_capture_time_ms_ = -1;
206 start_timestamp_ = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000207 _SSRC = 0;
208 _remoteSSRC = 0;
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000209 _cameraDelayMS = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000210 _sequenceNumberFIR = 0;
211 _tmmbr_Send = 0;
212 _packetOH_Send = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000213 _nextTimeToSendRTCP = 0;
214 _CSRCs = 0;
215 _appSend = false;
216 _appSubType = 0;
217
218 if(_appData)
219 {
220 delete [] _appData;
221 _appData = NULL;
222 }
223 _appLength = 0;
224
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000225 xrSendReceiverReferenceTimeEnabled_ = false;
226
niklase@google.com470e71d2011-07-07 08:21:25 +0000227 _xrSendVoIPMetric = false;
228
229 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
230 memset(_CNAME, 0, sizeof(_CNAME));
231 memset(_lastSendReport, 0, sizeof(_lastSendReport));
232 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000233 last_xr_rr_.clear();
edjee@google.com79b02892013-04-04 19:43:34 +0000234
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000235 memset(&packet_type_counter_, 0, sizeof(packet_type_counter_));
niklase@google.com470e71d2011-07-07 08:21:25 +0000236 return 0;
237}
238
239void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000240RTCPSender::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +0000241{
242 _id = id;
243}
244
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000245int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000246RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
247{
248 CriticalSectionScoped lock(_criticalSectionTransport);
249 _cbTransport = outgoingTransport;
250 return 0;
251}
252
253RTCPMethod
254RTCPSender::Status() const
255{
256 CriticalSectionScoped lock(_criticalSectionRTCPSender);
257 return _method;
258}
259
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000260int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000261RTCPSender::SetRTCPStatus(const RTCPMethod method)
262{
263 CriticalSectionScoped lock(_criticalSectionRTCPSender);
264 if(method != kRtcpOff)
265 {
266 if(_audio)
267 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000268 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000269 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000270 } else
271 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000272 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000273 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000274 }
275 }
276 _method = method;
277 return 0;
278}
279
280bool
281RTCPSender::Sending() const
282{
283 CriticalSectionScoped lock(_criticalSectionRTCPSender);
284 return _sending;
285}
286
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000287int32_t
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000288RTCPSender::SetSendingStatus(const FeedbackState& feedback_state, bool sending)
niklase@google.com470e71d2011-07-07 08:21:25 +0000289{
290 bool sendRTCPBye = false;
291 {
292 CriticalSectionScoped lock(_criticalSectionRTCPSender);
293
294 if(_method != kRtcpOff)
295 {
296 if(sending == false && _sending == true)
297 {
298 // Trigger RTCP bye
299 sendRTCPBye = true;
300 }
301 }
302 _sending = sending;
303 }
304 if(sendRTCPBye)
305 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000306 return SendRTCP(feedback_state, kRtcpBye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000307 }
308 return 0;
309}
310
311bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000312RTCPSender::REMB() const
313{
314 CriticalSectionScoped lock(_criticalSectionRTCPSender);
315 return _REMB;
316}
317
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000318int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000319RTCPSender::SetREMBStatus(const bool enable)
320{
321 CriticalSectionScoped lock(_criticalSectionRTCPSender);
322 _REMB = enable;
323 return 0;
324}
325
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000326int32_t
327RTCPSender::SetREMBData(const uint32_t bitrate,
328 const uint8_t numberOfSSRC,
329 const uint32_t* SSRC)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000330{
331 CriticalSectionScoped lock(_criticalSectionRTCPSender);
332 _rembBitrate = bitrate;
333
334 if(_sizeRembSSRC < numberOfSSRC)
335 {
336 delete [] _rembSSRC;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000337 _rembSSRC = new uint32_t[numberOfSSRC];
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000338 _sizeRembSSRC = numberOfSSRC;
339 }
340
341 _lengthRembSSRC = numberOfSSRC;
342 for (int i = 0; i < numberOfSSRC; i++)
343 {
344 _rembSSRC[i] = SSRC[i];
345 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000346 _sendREMB = true;
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000347 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
348 // throttled by the caller.
349 _nextTimeToSendRTCP = _clock->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000350 return 0;
351}
352
353bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000354RTCPSender::TMMBR() const
355{
356 CriticalSectionScoped lock(_criticalSectionRTCPSender);
357 return _TMMBR;
358}
359
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000360int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000361RTCPSender::SetTMMBRStatus(const bool enable)
362{
363 CriticalSectionScoped lock(_criticalSectionRTCPSender);
364 _TMMBR = enable;
365 return 0;
366}
367
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000368bool
369RTCPSender::IJ() const
370{
371 CriticalSectionScoped lock(_criticalSectionRTCPSender);
372 return _IJ;
373}
374
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000375int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000376RTCPSender::SetIJStatus(const bool enable)
377{
378 CriticalSectionScoped lock(_criticalSectionRTCPSender);
379 _IJ = enable;
380 return 0;
381}
382
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000383void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
384 start_timestamp_ = start_timestamp;
385}
386
387void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
388 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000389 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000390 last_rtp_timestamp_ = rtp_timestamp;
391 if (capture_time_ms < 0) {
392 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000393 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000394 } else {
395 last_frame_capture_time_ms_ = capture_time_ms;
396 }
397}
398
niklase@google.com470e71d2011-07-07 08:21:25 +0000399void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000400RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000401{
402 CriticalSectionScoped lock(_criticalSectionRTCPSender);
403
404 if(_SSRC != 0)
405 {
406 // not first SetSSRC, probably due to a collision
407 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000408 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000409 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000410 }
411 _SSRC = ssrc;
412}
413
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000414void RTCPSender::SetRemoteSSRC(uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000415{
416 CriticalSectionScoped lock(_criticalSectionRTCPSender);
417 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000418}
419
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000420int32_t
421RTCPSender::SetCameraDelay(const int32_t delayMS)
422{
423 CriticalSectionScoped lock(_criticalSectionRTCPSender);
424 if(delayMS > 1000 || delayMS < -1000)
425 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000426 LOG(LS_WARNING) << "Delay can't be larger than 1 second: "
427 << delayMS << " ms";
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000428 return -1;
429 }
430 _cameraDelayMS = delayMS;
431 return 0;
432}
433
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000434int32_t RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000435 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000436 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000437 cName[RTCP_CNAME_SIZE - 1] = 0;
438 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000439 return 0;
440}
441
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000442int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000443 if (!cName)
444 return -1;
445
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000446 CriticalSectionScoped lock(_criticalSectionRTCPSender);
447 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
448 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
449 return 0;
450}
451
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000452int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
453 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000454 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000455 CriticalSectionScoped lock(_criticalSectionRTCPSender);
456 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
457 return -1;
458 }
459 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000460 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
461 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000462 _csrcCNAMEs[SSRC] = ptr;
463 return 0;
464}
465
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000466int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000467 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000468 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000469 _csrcCNAMEs.find(SSRC);
470
471 if (it == _csrcCNAMEs.end()) {
472 return -1;
473 }
474 delete it->second;
475 _csrcCNAMEs.erase(it);
476 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000477}
478
479bool
480RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
481{
482/*
483 For audio we use a fix 5 sec interval
484
485 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000486 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
487 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000488
489
490From RFC 3550
491
492 MAX RTCP BW is 5% if the session BW
493 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000494 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000495
496 The RECOMMENDED value for the reduced minimum in seconds is 360
497 divided by the session bandwidth in kilobits/second. This minimum
498 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
499
500 If the participant has not yet sent an RTCP packet (the variable
501 initial is true), the constant Tmin is set to 2.5 seconds, else it
502 is set to 5 seconds.
503
504 The interval between RTCP packets is varied randomly over the
505 range [0.5,1.5] times the calculated interval to avoid unintended
506 synchronization of all participants
507
508 if we send
509 If the participant is a sender (we_sent true), the constant C is
510 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
511 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
512 number of senders.
513
514 if we receive only
515 If we_sent is not true, the constant C is set
516 to the average RTCP packet size divided by 75% of the RTCP
517 bandwidth. The constant n is set to the number of receivers
518 (members - senders). If the number of senders is greater than
519 25%, senders and receivers are treated together.
520
521 reconsideration NOT required for peer-to-peer
522 "timer reconsideration" is
523 employed. This algorithm implements a simple back-off mechanism
524 which causes users to hold back RTCP packet transmission if the
525 group sizes are increasing.
526
527 n = number of members
528 C = avg_size/(rtcpBW/4)
529
530 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
531
532 4. The calculated interval T is set to a number uniformly distributed
533 between 0.5 and 1.5 times the deterministic calculated interval.
534
535 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
536 for the fact that the timer reconsideration algorithm converges to
537 a value of the RTCP bandwidth below the intended average
538*/
539
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000540 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000541
542 CriticalSectionScoped lock(_criticalSectionRTCPSender);
543
niklase@google.com470e71d2011-07-07 08:21:25 +0000544 if(_method == kRtcpOff)
545 {
546 return false;
547 }
548
niklase@google.com470e71d2011-07-07 08:21:25 +0000549 if(!_audio && sendKeyframeBeforeRTP)
550 {
551 // for video key-frames we want to send the RTCP before the large key-frame
552 // if we have a 100 ms margin
553 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
554 }
555
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000556 if(now >= _nextTimeToSendRTCP)
niklase@google.com470e71d2011-07-07 08:21:25 +0000557 {
558 return true;
559
560 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
561 {
562 // wrap
563 return true;
564 }
565 return false;
566}
567
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000568uint32_t
569RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000570{
571 CriticalSectionScoped lock(_criticalSectionRTCPSender);
572
573 lastRTCPTime = _lastRTCPTime[0];
574 return _lastSendReport[0];
575}
576
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000577uint32_t
578RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000579{
580 CriticalSectionScoped lock(_criticalSectionRTCPSender);
581
582 // This is only saved when we are the sender
583 if((_lastSendReport[0] == 0) || (sendReport == 0))
584 {
585 return 0; // will be ignored
586 } else
587 {
588 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
589 {
590 if( _lastSendReport[i] == sendReport)
591 {
592 return _lastRTCPTime[i];
593 }
594 }
595 }
596 return 0;
597}
598
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000599bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
600 int64_t* time_ms) const {
601 CriticalSectionScoped lock(_criticalSectionRTCPSender);
602
603 if (last_xr_rr_.empty()) {
604 return false;
605 }
606 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
607 if (it == last_xr_rr_.end()) {
608 return false;
609 }
610 *time_ms = it->second;
611 return true;
612}
613
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000614void RTCPSender::GetPacketTypeCounter(
615 RtcpPacketTypeCounter* packet_counter) const {
616 CriticalSectionScoped lock(_criticalSectionRTCPSender);
617 *packet_counter = packet_type_counter_;
618}
619
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000620int32_t RTCPSender::AddExternalReportBlock(
621 uint32_t SSRC,
622 const RTCPReportBlock* reportBlock) {
623 CriticalSectionScoped lock(_criticalSectionRTCPSender);
624 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
625}
626
627int32_t RTCPSender::AddReportBlock(
628 uint32_t SSRC,
629 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
630 const RTCPReportBlock* reportBlock) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000631 assert(reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000632
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000633 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000634 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000635 return -1;
636 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000637 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000638 report_blocks->find(SSRC);
639 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000640 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000641 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000642 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000643 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
644 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000645 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000646 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000647}
648
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000649int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000650 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000651
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000652 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000653 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000654
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000655 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000656 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000657 }
658 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000659 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000660 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000661}
662
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000663int32_t RTCPSender::BuildSR(const FeedbackState& feedback_state,
664 uint8_t* rtcpbuffer,
665 int& pos,
666 uint32_t NTPsec,
667 uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000668{
669 // sanity
670 if(pos + 52 >= IP_PACKET_SIZE)
671 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000672 LOG(LS_WARNING) << "Failed to build Sender Report.";
niklase@google.com470e71d2011-07-07 08:21:25 +0000673 return -2;
674 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000675 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000676
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000677 uint32_t posNumberOfReportBlocks = pos;
678 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000679
680 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000681 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000682
683 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
684 {
685 // shift old
686 _lastSendReport[i+1] = _lastSendReport[i];
687 _lastRTCPTime[i+1] =_lastRTCPTime[i];
688 }
689
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000690 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000691 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000692
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000693 // The timestamp of this RTCP packet should be estimated as the timestamp of
694 // the frame being captured at this moment. We are calculating that
695 // timestamp as the last frame's timestamp + the time since the last frame
696 // was captured.
697 {
698 // Needs protection since this method is called on the process thread.
699 CriticalSectionScoped lock(_criticalSectionRTCPSender);
700 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
701 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000702 (feedback_state.frequency_hz / 1000);
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000703 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000704
705 // Add sender data
706 // Save for our length field
707 pos++;
708 pos++;
709
710 // Add our own SSRC
711 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
712 pos += 4;
713 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000714 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000715 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000716 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000717 pos += 4;
718 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
719 pos += 4;
720
721 //sender's packet count
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000722 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
723 feedback_state.packet_count_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000724 pos += 4;
725
726 //sender's octet count
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000727 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
728 feedback_state.byte_count_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000729 pos += 4;
730
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000731 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000732 int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
733 numberOfReportBlocks,
734 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000735 if(retVal < 0)
736 {
737 //
738 return retVal ;
739 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000740 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000741 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
742
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000743 uint16_t len = uint16_t((pos/4) -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000744 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
745 return 0;
746}
747
748
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000749int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000750 size_t lengthCname = strlen(_CNAME);
751 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000752
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000753 // sanity
754 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000755 LOG(LS_WARNING) << "Failed to build SDEC.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000756 return -2;
757 }
758 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000759
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000760 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000761 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
762 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000763
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000764 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000765 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000766 pos++;
767 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000768
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000769 // Add our own SSRC
770 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
771 pos += 4;
772
773 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000774 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000775
776 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000777 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000778
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000779 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000780
781 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
782 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000783 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000784
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000785 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000786 // We must have a zero field even if we have an even multiple of 4 bytes
787 if ((pos % 4) == 0) {
788 padding++;
789 rtcpbuffer[pos++]=0;
790 }
791 while ((pos % 4) != 0) {
792 padding++;
793 rtcpbuffer[pos++]=0;
794 }
795 SDESLength += padding;
796
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000797 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000798 _csrcCNAMEs.begin();
799
800 for(; it != _csrcCNAMEs.end(); it++) {
801 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000802 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000803
804 // Add SSRC
805 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000806 pos += 4;
807
808 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000809 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000810
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000811 size_t length = strlen(cname->name);
812 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000813
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000814 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000815 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000816
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000817 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000818
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000819 pos += length;
820 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000821 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000822
823 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000824 if((pos % 4) == 0){
825 padding++;
826 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000827 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000828 while((pos % 4) != 0){
829 padding++;
830 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000831 }
832 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000833 }
834 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000835 uint16_t buffer_length = (SDESLength / 4) - 1;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000836 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
837 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000838 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000839}
840
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000841int32_t
842RTCPSender::BuildRR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000843 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000844 const uint32_t NTPsec,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000845 const uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000846{
847 // sanity one block
848 if(pos + 32 >= IP_PACKET_SIZE)
849 {
850 return -2;
851 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000852 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000853
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000854 rtcpbuffer[pos++]=(uint8_t)0x80;
855 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000856
857 // Save for our length field
858 pos++;
859 pos++;
860
861 // Add our own SSRC
862 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
863 pos += 4;
864
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000865 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000866 int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
867 numberOfReportBlocks,
868 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000869 if(retVal < 0)
870 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000871 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000872 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000873 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000874 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
875
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000876 uint16_t len = uint16_t((pos)/4 -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000877 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
878 return 0;
879}
880
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000881// From RFC 5450: Transmission Time Offsets in RTP Streams.
882// 0 1 2 3
883// 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
884// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
885// hdr |V=2|P| RC | PT=IJ=195 | length |
886// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
887// | inter-arrival jitter |
888// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
889// . .
890// . .
891// . .
892// | inter-arrival jitter |
893// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
894//
895// If present, this RTCP packet must be placed after a receiver report
896// (inside a compound RTCP packet), and MUST have the same value for RC
897// (reception report count) as the receiver report.
898
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000899int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000900RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000901 uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000902 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000903 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000904{
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000905 if (external_report_blocks_.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000906 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000907 // TODO(andresp): Remove external report blocks since they are not
908 // supported.
909 LOG(LS_ERROR) << "Handling of external report blocks not implemented.";
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000910 return 0;
911 }
912
913 // sanity
914 if(pos + 8 >= IP_PACKET_SIZE)
915 {
916 return -2;
917 }
918 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000919 uint8_t RC = 1;
920 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
921 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000922
923 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000924 rtcpbuffer[pos++]=(uint8_t)0;
925 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000926
927 // Add inter-arrival jitter
928 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
929 jitterTransmissionTimeOffset);
930 pos += 4;
931 return 0;
932}
933
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000934int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000935RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000936{
937 // sanity
938 if(pos + 12 >= IP_PACKET_SIZE)
939 {
940 return -2;
941 }
942 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000943 uint8_t FMT = 1;
944 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
945 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000946
947 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000948 rtcpbuffer[pos++]=(uint8_t)0;
949 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000950
951 // Add our own SSRC
952 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
953 pos += 4;
954
955 // Add the remote SSRC
956 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
957 pos += 4;
958 return 0;
959}
960
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000961int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000962 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000963 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000964 // sanity
965 if(pos + 20 >= IP_PACKET_SIZE) {
966 return -2;
967 }
968 if (!repeat) {
969 _sequenceNumberFIR++; // do not increase if repetition
970 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000971
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000972 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000973 uint8_t FMT = 4;
974 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
975 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000976
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000977 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000978 rtcpbuffer[pos++] = (uint8_t)0;
979 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000980
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000981 // Add our own SSRC
982 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
983 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000984
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000985 // RFC 5104 4.3.1.2. Semantics
986 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000987 rtcpbuffer[pos++] = (uint8_t)0;
988 rtcpbuffer[pos++] = (uint8_t)0;
989 rtcpbuffer[pos++] = (uint8_t)0;
990 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000991
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000992 // Additional Feedback Control Information (FCI)
993 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
994 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000995
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000996 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
997 rtcpbuffer[pos++] = (uint8_t)0;
998 rtcpbuffer[pos++] = (uint8_t)0;
999 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001000 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001001}
1002
1003/*
1004 0 1 2 3
1005 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
1006 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1007 | First | Number | PictureID |
1008 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1009*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001010int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001011RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +00001012{
1013 // sanity
1014 if(pos + 16 >= IP_PACKET_SIZE)
1015 {
1016 return -2;
1017 }
1018 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001019 uint8_t FMT = 2;
1020 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1021 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001022
1023 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001024 rtcpbuffer[pos++]=(uint8_t)0;
1025 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +00001026
1027 // Add our own SSRC
1028 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1029 pos += 4;
1030
1031 // Add the remote SSRC
1032 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1033 pos += 4;
1034
1035 // Add first, number & picture ID 6 bits
1036 // first = 0, 13 - bits
1037 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001038 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +00001039 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
1040 pos += 4;
1041 return 0;
1042}
1043
1044/*
1045 0 1 2 3
1046 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
1047 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1048 | PB |0| Payload Type| Native RPSI bit string |
1049 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1050 | defined per codec ... | Padding (0) |
1051 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1052*/
1053/*
1054* Note: not generic made for VP8
1055*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001056int32_t
1057RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001058 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001059 const uint64_t pictureID,
1060 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +00001061{
1062 // sanity
1063 if(pos + 24 >= IP_PACKET_SIZE)
1064 {
1065 return -2;
1066 }
1067 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001068 uint8_t FMT = 3;
1069 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1070 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001071
1072 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001073 uint32_t bitsRequired = 7;
1074 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001075 while((pictureID>>bitsRequired) > 0)
1076 {
1077 bitsRequired += 7;
1078 bytesRequired++;
1079 }
1080
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001081 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001082 if(bytesRequired > 6)
1083 {
1084 size = 5;
1085 } else if(bytesRequired > 2)
1086 {
1087 size = 4;
1088 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001089 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001090 rtcpbuffer[pos++]=size;
1091
1092 // Add our own SSRC
1093 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1094 pos += 4;
1095
1096 // Add the remote SSRC
1097 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1098 pos += 4;
1099
1100 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001101 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001102 if(paddingBytes == 4)
1103 {
1104 paddingBytes = 0;
1105 }
1106 // add padding length in bits
1107 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1108 pos++;
1109
1110 // add payload type
1111 rtcpbuffer[pos] = payloadType;
1112 pos++;
1113
1114 // add picture ID
1115 for(int i = bytesRequired-1; i > 0; i--)
1116 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001117 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001118 pos++;
1119 }
1120 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001121 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001122 pos++;
1123
1124 // add padding
1125 for(int j = 0; j <paddingBytes; j++)
1126 {
1127 rtcpbuffer[pos] = 0;
1128 pos++;
1129 }
1130 return 0;
1131}
1132
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001133int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001134RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001135{
1136 // sanity
1137 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1138 {
1139 return -2;
1140 }
1141 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001142 uint8_t FMT = 15;
1143 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1144 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001145
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001146 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001147 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1148
1149 // Add our own SSRC
1150 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1151 pos += 4;
1152
1153 // Remote SSRC must be 0
1154 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1155 pos += 4;
1156
1157 rtcpbuffer[pos++]='R';
1158 rtcpbuffer[pos++]='E';
1159 rtcpbuffer[pos++]='M';
1160 rtcpbuffer[pos++]='B';
1161
1162 rtcpbuffer[pos++] = _lengthRembSSRC;
1163 // 6 bit Exp
1164 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001165 uint8_t brExp = 0;
1166 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001167 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001168 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001169 {
1170 brExp = i;
1171 break;
1172 }
1173 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001174 const uint32_t brMantissa = (_rembBitrate >> brExp);
1175 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1176 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1177 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001178
1179 for (int i = 0; i < _lengthRembSSRC; i++)
1180 {
1181 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1182 pos += 4;
1183 }
1184 return 0;
1185}
1186
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001187void
1188RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001189{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001190 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001191 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001192}
1193
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001194int32_t RTCPSender::BuildTMMBR(ModuleRtpRtcpImpl* rtp_rtcp_module,
1195 uint8_t* rtcpbuffer,
1196 int& pos) {
1197 if (rtp_rtcp_module == NULL)
1198 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001199 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1200 // If the sender is an owner of the TMMBN -> send TMMBR
1201 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1202
niklase@google.com470e71d2011-07-07 08:21:25 +00001203 // get current bounding set from RTCP receiver
1204 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001205 // store in candidateSet, allocates one extra slot
1206 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001207
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001208 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1209 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1210 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001211 int32_t lengthOfBoundingSet =
1212 rtp_rtcp_module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001213
1214 if(lengthOfBoundingSet > 0)
1215 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001216 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001217 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001218 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1219 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001220 {
1221 // do not send the same tuple
1222 return 0;
1223 }
1224 }
1225 if(!tmmbrOwner)
1226 {
1227 // use received bounding set as candidate set
1228 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001229 candidateSet->SetEntry(lengthOfBoundingSet,
1230 _tmmbr_Send,
1231 _packetOH_Send,
1232 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001233 int numCandidates = lengthOfBoundingSet+ 1;
1234
1235 // find bounding set
1236 TMMBRSet* boundingSet = NULL;
1237 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1238 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1239 {
1240 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1241 }
1242 if(!tmmbrOwner)
1243 {
1244 // did not enter bounding set, no meaning to send this request
1245 return 0;
1246 }
1247 }
1248 }
1249
1250 if(_tmmbr_Send)
1251 {
1252 // sanity
1253 if(pos + 20 >= IP_PACKET_SIZE)
1254 {
1255 return -2;
1256 }
1257 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001258 uint8_t FMT = 3;
1259 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1260 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001261
1262 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001263 rtcpbuffer[pos++]=(uint8_t)0;
1264 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001265
1266 // Add our own SSRC
1267 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1268 pos += 4;
1269
1270 // RFC 5104 4.2.1.2. Semantics
1271
1272 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001273 rtcpbuffer[pos++]=(uint8_t)0;
1274 rtcpbuffer[pos++]=(uint8_t)0;
1275 rtcpbuffer[pos++]=(uint8_t)0;
1276 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001277
1278 // Additional Feedback Control Information (FCI)
1279 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1280 pos += 4;
1281
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001282 uint32_t bitRate = _tmmbr_Send*1000;
1283 uint32_t mmbrExp = 0;
1284 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001285 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001286 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001287 {
1288 mmbrExp = i;
1289 break;
1290 }
1291 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001292 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001293
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001294 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1295 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1296 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1297 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001298 }
1299 return 0;
1300}
1301
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001302int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001303RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001304{
1305 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1306 if(boundingSet == NULL)
1307 {
1308 return -1;
1309 }
1310 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001311 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001312 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001313 LOG(LS_WARNING) << "Failed to build TMMBN.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001314 return -2;
1315 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001316 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001317 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001318 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1319 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001320
1321 //Add length later
1322 int posLength = pos;
1323 pos++;
1324 pos++;
1325
1326 // Add our own SSRC
1327 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1328 pos += 4;
1329
1330 // RFC 5104 4.2.2.2. Semantics
1331
1332 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001333 rtcpbuffer[pos++]=(uint8_t)0;
1334 rtcpbuffer[pos++]=(uint8_t)0;
1335 rtcpbuffer[pos++]=(uint8_t)0;
1336 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001337
1338 // Additional Feedback Control Information (FCI)
1339 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001340 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001341 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001342 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001343 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001344 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001345 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1346 pos += 4;
1347
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001348 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1349 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001350 for(int i=0; i<64; i++)
1351 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001352 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001353 {
1354 mmbrExp = i;
1355 break;
1356 }
1357 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001358 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1359 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001360
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001361 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1362 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1363 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1364 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001365 numBoundingSet++;
1366 }
1367 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001368 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1369 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1370 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001371 return 0;
1372}
1373
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001374int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001375RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001376{
1377 // sanity
1378 if(_appData == NULL)
1379 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001380 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001381 return -1;
1382 }
1383 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1384 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001385 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001386 return -2;
1387 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001388 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001389
1390 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001391 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001392
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001393 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1394 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1395 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001396
1397 // Add our own SSRC
1398 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1399 pos += 4;
1400
1401 // Add our application name
1402 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1403 pos += 4;
1404
1405 // Add the data
1406 memcpy(rtcpbuffer +pos, _appData,_appLength);
1407 pos += _appLength;
1408 return 0;
1409}
1410
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001411int32_t
1412RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001413 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001414 const int32_t nackSize,
1415 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001416 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001417{
1418 // sanity
1419 if(pos + 16 >= IP_PACKET_SIZE)
1420 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001421 LOG(LS_WARNING) << "Failed to build NACK.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001422 return -2;
1423 }
1424
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001425 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001426 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001427 uint8_t FMT = 1;
1428 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1429 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001430
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001431 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001432 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001433 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001434
1435 // Add our own SSRC
1436 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1437 pos += 4;
1438
1439 // Add the remote SSRC
1440 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1441 pos += 4;
1442
edjee@google.com79b02892013-04-04 19:43:34 +00001443 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001444 // Build NACK bitmasks and write them to the RTCP message.
1445 // The nack list should be sorted and not contain duplicates if one
1446 // wants to build the smallest rtcp nack packet.
1447 int numOfNackFields = 0;
1448 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1449 (IP_PACKET_SIZE - pos) / 4);
1450 int i = 0;
1451 while (i < nackSize && numOfNackFields < maxNackFields) {
1452 stringBuilder.PushNACK(nackList[i]);
1453 uint16_t nack = nackList[i++];
1454 uint16_t bitmask = 0;
1455 while (i < nackSize) {
1456 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1457 if (shift >= 0 && shift <= 15) {
1458 stringBuilder.PushNACK(nackList[i]);
1459 bitmask |= (1 << shift);
1460 ++i;
1461 } else {
1462 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001463 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001464 }
1465 // Write the sequence number and the bitmask to the packet.
1466 assert(pos + 4 < IP_PACKET_SIZE);
1467 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
1468 pos += 2;
1469 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
1470 pos += 2;
1471 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001472 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001473 if (i != nackSize) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001474 LOG(LS_WARNING) << "Nack list to large for one packet.";
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001475 }
1476 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001477 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001478 return 0;
1479}
1480
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001481int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001482RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001483{
1484 // sanity
1485 if(pos + 8 >= IP_PACKET_SIZE)
1486 {
1487 return -2;
1488 }
1489 if(_includeCSRCs)
1490 {
1491 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001492 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1493 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001494
1495 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001496 rtcpbuffer[pos++]=(uint8_t)0;
1497 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001498
1499 // Add our own SSRC
1500 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1501 pos += 4;
1502
1503 // add CSRCs
1504 for(int i = 0; i < _CSRCs; i++)
1505 {
1506 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1507 pos += 4;
1508 }
1509 } else
1510 {
1511 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001512 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1513 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001514
1515 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001516 rtcpbuffer[pos++]=(uint8_t)0;
1517 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001518
1519 // Add our own SSRC
1520 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1521 pos += 4;
1522 }
1523 return 0;
1524}
1525
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001526int32_t RTCPSender::BuildReceiverReferenceTime(uint8_t* buffer,
1527 int& pos,
1528 uint32_t ntp_sec,
1529 uint32_t ntp_frac) {
1530 const int kRrTimeBlockLength = 20;
1531 if (pos + kRrTimeBlockLength >= IP_PACKET_SIZE) {
1532 return -2;
1533 }
1534
1535 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) {
1536 last_xr_rr_.erase(last_xr_rr_.begin());
1537 }
1538 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
1539 RTCPUtility::MidNtp(ntp_sec, ntp_frac),
1540 Clock::NtpToMs(ntp_sec, ntp_frac)));
1541
1542 // Add XR header.
1543 buffer[pos++] = 0x80;
1544 buffer[pos++] = 207;
1545 buffer[pos++] = 0; // XR packet length.
1546 buffer[pos++] = 4; // XR packet length.
1547
1548 // Add our own SSRC.
1549 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
1550 pos += 4;
1551
1552 // 0 1 2 3
1553 // 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
1554 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1555 // | BT=4 | reserved | block length = 2 |
1556 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1557 // | NTP timestamp, most significant word |
1558 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1559 // | NTP timestamp, least significant word |
1560 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1561
1562 // Add Receiver Reference Time Report block.
1563 buffer[pos++] = 4; // BT.
1564 buffer[pos++] = 0; // Reserved.
1565 buffer[pos++] = 0; // Block length.
1566 buffer[pos++] = 2; // Block length.
1567
1568 // NTP timestamp.
1569 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, ntp_sec);
1570 pos += 4;
1571 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, ntp_frac);
1572 pos += 4;
1573
1574 return 0;
1575}
1576
1577int32_t RTCPSender::BuildDlrr(uint8_t* buffer,
1578 int& pos,
1579 const RtcpReceiveTimeInfo& info) {
1580 const int kDlrrBlockLength = 24;
1581 if (pos + kDlrrBlockLength >= IP_PACKET_SIZE) {
1582 return -2;
1583 }
1584
1585 // Add XR header.
1586 buffer[pos++] = 0x80;
1587 buffer[pos++] = 207;
1588 buffer[pos++] = 0; // XR packet length.
1589 buffer[pos++] = 5; // XR packet length.
1590
1591 // Add our own SSRC.
1592 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
1593 pos += 4;
1594
1595 // 0 1 2 3
1596 // 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
1597 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1598 // | BT=5 | reserved | block length |
1599 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1600 // | SSRC_1 (SSRC of first receiver) | sub-
1601 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1602 // | last RR (LRR) | 1
1603 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1604 // | delay since last RR (DLRR) |
1605 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1606 // | SSRC_2 (SSRC of second receiver) | sub-
1607 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1608 // : ... : 2
1609
1610 // Add DLRR sub block.
1611 buffer[pos++] = 5; // BT.
1612 buffer[pos++] = 0; // Reserved.
1613 buffer[pos++] = 0; // Block length.
1614 buffer[pos++] = 3; // Block length.
1615
1616 // NTP timestamp.
1617 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, info.sourceSSRC);
1618 pos += 4;
1619 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, info.lastRR);
1620 pos += 4;
1621 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, info.delaySinceLastRR);
1622 pos += 4;
1623
1624 return 0;
1625}
1626
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001627int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001628RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001629{
1630 // sanity
1631 if(pos + 44 >= IP_PACKET_SIZE)
1632 {
1633 return -2;
1634 }
1635
1636 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001637 rtcpbuffer[pos++]=(uint8_t)0x80;
1638 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001639
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001640 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001641
1642 // handle length later on
1643 pos++;
1644 pos++;
1645
1646 // Add our own SSRC
1647 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1648 pos += 4;
1649
1650 // Add a VoIP metrics block
1651 rtcpbuffer[pos++]=7;
1652 rtcpbuffer[pos++]=0;
1653 rtcpbuffer[pos++]=0;
1654 rtcpbuffer[pos++]=8;
1655
1656 // Add the remote SSRC
1657 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1658 pos += 4;
1659
1660 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1661 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1662 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1663 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1664
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001665 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1666 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1667 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1668 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001669
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001670 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1671 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1672 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1673 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001674
1675 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1676 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1677 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1678 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1679
1680 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1681 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1682 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1683 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1684
1685 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1686 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001687 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1688 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001689
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001690 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1691 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1692 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1693 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001694
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001695 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1696 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001697 return 0;
1698}
1699
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001700int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
1701 uint32_t packetTypeFlags,
1702 int32_t nackSize,
1703 const uint16_t* nackList,
1704 bool repeat,
1705 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001706 {
1707 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1708 if(_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001709 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001710 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001711 return -1;
1712 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001713 }
1714 uint8_t rtcp_buffer[IP_PACKET_SIZE];
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001715 int rtcp_length = PrepareRTCP(feedback_state,
1716 packetTypeFlags,
1717 nackSize,
1718 nackList,
1719 repeat,
1720 pictureID,
1721 rtcp_buffer,
1722 IP_PACKET_SIZE);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001723 if (rtcp_length < 0) {
1724 return -1;
1725 }
1726 // Sanity don't send empty packets.
1727 if (rtcp_length == 0)
1728 {
1729 return -1;
1730 }
1731 return SendToNetwork(rtcp_buffer, static_cast<uint16_t>(rtcp_length));
1732}
1733
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001734int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
1735 uint32_t packetTypeFlags,
1736 int32_t nackSize,
1737 const uint16_t* nackList,
1738 bool repeat,
1739 uint64_t pictureID,
1740 uint8_t* rtcp_buffer,
1741 int buffer_size) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001742 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1743 // Collect the received information.
1744 uint32_t NTPsec = 0;
1745 uint32_t NTPfrac = 0;
1746 uint32_t jitterTransmissionOffset = 0;
1747 int position = 0;
1748
1749 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1750
1751 if(_TMMBR ) // Attach TMMBR to send and receive reports.
1752 {
1753 rtcpPacketTypeFlags |= kRtcpTmmbr;
1754 }
1755 if(_appSend)
1756 {
1757 rtcpPacketTypeFlags |= kRtcpApp;
1758 _appSend = false;
1759 }
1760 if(_REMB && _sendREMB)
1761 {
1762 // Always attach REMB to SR if that is configured. Note that REMB is
1763 // only sent on one of the RTP modules in the REMB group.
1764 rtcpPacketTypeFlags |= kRtcpRemb;
1765 }
1766 if(_xrSendVoIPMetric)
1767 {
1768 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1769 _xrSendVoIPMetric = false;
1770 }
1771 if(_sendTMMBN) // Set when having received a TMMBR.
1772 {
1773 rtcpPacketTypeFlags |= kRtcpTmmbn;
1774 _sendTMMBN = false;
1775 }
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001776 if (rtcpPacketTypeFlags & kRtcpReport)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001777 {
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001778 if (xrSendReceiverReferenceTimeEnabled_ && !_sending)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001779 {
1780 rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
1781 }
1782 if (feedback_state.has_last_xr_rr)
1783 {
1784 rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
1785 }
1786 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001787 if(_method == kRtcpCompound)
1788 {
1789 if(_sending)
1790 {
1791 rtcpPacketTypeFlags |= kRtcpSr;
1792 } else
1793 {
1794 rtcpPacketTypeFlags |= kRtcpRr;
1795 }
1796 } else if(_method == kRtcpNonCompound)
1797 {
1798 if(rtcpPacketTypeFlags & kRtcpReport)
1799 {
1800 if(_sending)
1801 {
1802 rtcpPacketTypeFlags |= kRtcpSr;
1803 } else
1804 {
1805 rtcpPacketTypeFlags |= kRtcpRr;
1806 }
1807 }
1808 }
1809 if( rtcpPacketTypeFlags & kRtcpRr ||
1810 rtcpPacketTypeFlags & kRtcpSr)
1811 {
1812 // generate next time to send a RTCP report
1813 // seeded from RTP constructor
1814 int32_t random = rand() % 1000;
1815 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1816
1817 if(_audio)
1818 {
1819 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1820 (RTCP_INTERVAL_AUDIO_MS*random/1000);
1821 }else
1822 {
1823 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1824 if(_sending)
1825 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001826 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1827 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1828 if (send_bitrate_kbit != 0)
1829 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001830 }
1831 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1832 {
1833 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1834 }
1835 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1836 }
1837 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1838 }
1839
1840 // If the data does not fit in the packet we fill it as much as possible.
1841 int32_t buildVal = 0;
1842
1843 // We need to send our NTP even if we haven't received any reports.
1844 _clock->CurrentNtp(NTPsec, NTPfrac);
1845 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1846 StatisticianMap statisticians =
1847 receive_statistics_->GetActiveStatisticians();
1848 if (!statisticians.empty()) {
1849 StatisticianMap::const_iterator it;
1850 int i;
1851 for (it = statisticians.begin(), i = 0; it != statisticians.end();
1852 ++it, ++i) {
1853 RTCPReportBlock report_block;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001854 if (PrepareReport(
1855 feedback_state, it->second, &report_block, &NTPsec, &NTPfrac))
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001856 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1857 }
1858 if (_IJ && !statisticians.empty()) {
1859 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1860 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001861 }
1862 }
1863
1864 if(rtcpPacketTypeFlags & kRtcpSr)
1865 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001866 buildVal = BuildSR(feedback_state, rtcp_buffer, position, NTPsec, NTPfrac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001867 if (buildVal == -1) {
1868 return -1;
1869 } else if (buildVal == -2) {
1870 return position;
1871 }
1872 buildVal = BuildSDEC(rtcp_buffer, position);
1873 if (buildVal == -1) {
1874 return -1;
1875 } else if (buildVal == -2) {
1876 return position;
1877 }
1878 }else if(rtcpPacketTypeFlags & kRtcpRr)
1879 {
1880 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1881 if (buildVal == -1) {
1882 return -1;
1883 } else if (buildVal == -2) {
1884 return position;
1885 }
1886 // only of set
1887 if(_CNAME[0] != 0)
1888 {
1889 buildVal = BuildSDEC(rtcp_buffer, position);
1890 if (buildVal == -1) {
1891 return -1;
1892 }
1893 }
1894 }
1895 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1896 {
1897 // If present, this RTCP packet must be placed after a
1898 // receiver report.
1899 buildVal = BuildExtendedJitterReport(rtcp_buffer,
1900 position,
1901 jitterTransmissionOffset);
1902 if (buildVal == -1) {
1903 return -1;
1904 } else if (buildVal == -2) {
1905 return position;
1906 }
1907 }
1908 if(rtcpPacketTypeFlags & kRtcpPli)
1909 {
1910 buildVal = BuildPLI(rtcp_buffer, position);
1911 if (buildVal == -1) {
1912 return -1;
1913 } else if (buildVal == -2) {
1914 return position;
1915 }
1916 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001917 ++packet_type_counter_.pli_packets;
1918 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC,
1919 packet_type_counter_.pli_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001920 }
1921 if(rtcpPacketTypeFlags & kRtcpFir)
1922 {
1923 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1924 if (buildVal == -1) {
1925 return -1;
1926 } else if (buildVal == -2) {
1927 return position;
1928 }
1929 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001930 ++packet_type_counter_.fir_packets;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001931 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001932 packet_type_counter_.fir_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001933 }
1934 if(rtcpPacketTypeFlags & kRtcpSli)
1935 {
1936 buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1937 if (buildVal == -1) {
1938 return -1;
1939 } else if (buildVal == -2) {
1940 return position;
1941 }
1942 }
1943 if(rtcpPacketTypeFlags & kRtcpRpsi)
1944 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001945 const int8_t payloadType = feedback_state.send_payload_type;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001946 if (payloadType == -1) {
1947 return -1;
1948 }
1949 buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1950 (uint8_t)payloadType);
1951 if (buildVal == -1) {
1952 return -1;
1953 } else if (buildVal == -2) {
1954 return position;
1955 }
1956 }
1957 if(rtcpPacketTypeFlags & kRtcpRemb)
1958 {
1959 buildVal = BuildREMB(rtcp_buffer, position);
1960 if (buildVal == -1) {
1961 return -1;
1962 } else if (buildVal == -2) {
1963 return position;
1964 }
1965 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1966 }
1967 if(rtcpPacketTypeFlags & kRtcpBye)
1968 {
1969 buildVal = BuildBYE(rtcp_buffer, position);
1970 if (buildVal == -1) {
1971 return -1;
1972 } else if (buildVal == -2) {
1973 return position;
1974 }
1975 }
1976 if(rtcpPacketTypeFlags & kRtcpApp)
1977 {
1978 buildVal = BuildAPP(rtcp_buffer, position);
1979 if (buildVal == -1) {
1980 return -1;
1981 } else if (buildVal == -2) {
1982 return position;
1983 }
1984 }
1985 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1986 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001987 buildVal = BuildTMMBR(feedback_state.module, rtcp_buffer, position);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001988 if (buildVal == -1) {
1989 return -1;
1990 } else if (buildVal == -2) {
1991 return position;
1992 }
1993 }
1994 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1995 {
1996 buildVal = BuildTMMBN(rtcp_buffer, position);
1997 if (buildVal == -1) {
1998 return -1;
1999 } else if (buildVal == -2) {
2000 return position;
2001 }
2002 }
2003 if(rtcpPacketTypeFlags & kRtcpNack)
2004 {
2005 std::string nackString;
2006 buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
2007 &nackString);
2008 if (buildVal == -1) {
2009 return -1;
2010 } else if (buildVal == -2) {
2011 return position;
2012 }
2013 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
2014 "nacks", TRACE_STR_COPY(nackString.c_str()));
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00002015 ++packet_type_counter_.nack_packets;
2016 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC,
2017 packet_type_counter_.nack_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002018 }
2019 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
2020 {
2021 buildVal = BuildVoIPMetric(rtcp_buffer, position);
2022 if (buildVal == -1) {
2023 return -1;
2024 } else if (buildVal == -2) {
2025 return position;
2026 }
2027 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002028 if (rtcpPacketTypeFlags & kRtcpXrReceiverReferenceTime)
2029 {
2030 buildVal = BuildReceiverReferenceTime(rtcp_buffer,
2031 position,
2032 NTPsec,
2033 NTPfrac);
2034 if (buildVal == -1) {
2035 return -1;
2036 } else if (buildVal == -2) {
2037 return position;
2038 }
2039 }
2040 if (rtcpPacketTypeFlags & kRtcpXrDlrrReportBlock)
2041 {
2042 buildVal = BuildDlrr(rtcp_buffer, position, feedback_state.last_xr_rr);
2043 if (buildVal == -1) {
2044 return -1;
2045 } else if (buildVal == -2) {
2046 return position;
2047 }
2048 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002049 return position;
2050}
2051
2052bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
2053 return Status() == kRtcpCompound ||
2054 (rtcp_packet_type & kRtcpReport) ||
2055 (rtcp_packet_type & kRtcpSr) ||
2056 (rtcp_packet_type & kRtcpRr);
2057}
2058
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002059bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
2060 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002061 RTCPReportBlock* report_block,
2062 uint32_t* ntp_secs, uint32_t* ntp_frac) {
2063 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00002064 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002065 if (!statistician->GetStatistics(&stats, true))
2066 return false;
2067 report_block->fractionLost = stats.fraction_lost;
2068 report_block->cumulativeLost = stats.cumulative_lost;
2069 report_block->extendedHighSeqNum =
2070 stats.extended_max_sequence_number;
2071 report_block->jitter = stats.jitter;
2072
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002073 // get our NTP as late as possible to avoid a race
2074 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
2075
2076 // Delay since last received report
2077 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002078 if ((feedback_state.last_rr_ntp_secs != 0) ||
2079 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002080 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
2081 uint32_t now=*ntp_secs&0x0000FFFF;
2082 now <<=16;
2083 now += (*ntp_frac&0xffff0000)>>16;
2084
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002085 uint32_t receiveTime = feedback_state.last_rr_ntp_secs&0x0000FFFF;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002086 receiveTime <<=16;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002087 receiveTime += (feedback_state.last_rr_ntp_frac&0xffff0000)>>16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002088
2089 delaySinceLastReceivedSR = now-receiveTime;
2090 }
2091 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002092 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002093 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00002094}
2095
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002096int32_t
2097RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
2098 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002099{
2100 CriticalSectionScoped lock(_criticalSectionTransport);
2101 if(_cbTransport)
2102 {
2103 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
2104 {
2105 return 0;
2106 }
2107 }
2108 return -1;
2109}
2110
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002111int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002112RTCPSender::SetCSRCStatus(const bool include)
2113{
2114 _includeCSRCs = include;
2115 return 0;
2116}
2117
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002118int32_t
2119RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
2120 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00002121{
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002122 assert(arrLength <= kRtpCsrcSize);
niklase@google.com470e71d2011-07-07 08:21:25 +00002123 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2124
2125 for(int i = 0; i < arrLength;i++)
2126 {
2127 _CSRC[i] = arrOfCSRC[i];
2128 }
2129 _CSRCs = arrLength;
2130 return 0;
2131}
2132
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002133int32_t
2134RTCPSender::SetApplicationSpecificData(const uint8_t subType,
2135 const uint32_t name,
2136 const uint8_t* data,
2137 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002138{
2139 if(length %4 != 0)
2140 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002141 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
niklase@google.com470e71d2011-07-07 08:21:25 +00002142 return -1;
2143 }
2144 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2145
2146 if(_appData)
2147 {
2148 delete [] _appData;
2149 }
2150
2151 _appSend = true;
2152 _appSubType = subType;
2153 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002154 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002155 _appLength = length;
2156 memcpy(_appData, data, length);
2157 return 0;
2158}
2159
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002160int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002161RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2162{
2163 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2164 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2165
2166 _xrSendVoIPMetric = true;
2167 return 0;
2168}
2169
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002170void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
2171 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2172 xrSendReceiverReferenceTimeEnabled_ = enable;
2173}
2174
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00002175bool RTCPSender::RtcpXrReceiverReferenceTime() const {
2176 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2177 return xrSendReceiverReferenceTimeEnabled_;
2178}
2179
niklase@google.com470e71d2011-07-07 08:21:25 +00002180// called under critsect _criticalSectionRTCPSender
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002181int32_t RTCPSender::WriteAllReportBlocksToBuffer(
2182 uint8_t* rtcpbuffer,
2183 int pos,
2184 uint8_t& numberOfReportBlocks,
2185 const uint32_t NTPsec,
2186 const uint32_t NTPfrac) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002187 numberOfReportBlocks = external_report_blocks_.size();
2188 numberOfReportBlocks += internal_report_blocks_.size();
2189 if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002190 LOG(LS_WARNING) << "Can't fit all report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002191 return -1;
2192 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002193 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2194 while (!internal_report_blocks_.empty()) {
2195 delete internal_report_blocks_.begin()->second;
2196 internal_report_blocks_.erase(internal_report_blocks_.begin());
2197 }
2198 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2199 return pos;
2200}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002201
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002202int32_t RTCPSender::WriteReportBlocksToBuffer(
2203 uint8_t* rtcpbuffer,
2204 int32_t position,
2205 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2206 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2207 report_blocks.begin();
2208 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002209 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002210 RTCPReportBlock* reportBlock = it->second;
2211 if (reportBlock) {
2212 // Remote SSRC
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002213 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position, remoteSSRC);
2214 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002215
2216 // fraction lost
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002217 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002218
2219 // cumulative loss
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002220 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002221 reportBlock->cumulativeLost);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002222 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002223
2224 // extended highest seq_no, contain the highest sequence number received
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002225 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002226 reportBlock->extendedHighSeqNum);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002227 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002228
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002229 // Jitter
2230 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002231 reportBlock->jitter);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002232 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002233
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002234 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002235 reportBlock->lastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002236 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002237
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002238 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002239 reportBlock->delaySinceLastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002240 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002241 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002242 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002243 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00002244}
2245
2246// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002247int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002248RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002249 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002250{
2251 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2252
2253 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2254 {
2255 _sendTMMBN = true;
2256 return 0;
2257 }
2258 return -1;
2259}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002260} // namespace webrtc