blob: fa129abe04c3bcd00d1439fab487755769e49228 [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;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000333
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000334 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;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000339 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000340
341 _lengthRembSSRC = numberOfSSRC;
342 for (int i = 0; i < numberOfSSRC; i++)
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000343 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000344 _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::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000435 if (!cName)
436 return -1;
437
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000438 CriticalSectionScoped lock(_criticalSectionRTCPSender);
439 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
440 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
441 return 0;
442}
443
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000444int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
445 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000446 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000447 CriticalSectionScoped lock(_criticalSectionRTCPSender);
448 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
449 return -1;
450 }
451 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000452 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
453 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000454 _csrcCNAMEs[SSRC] = ptr;
455 return 0;
456}
457
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000458int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000459 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000460 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000461 _csrcCNAMEs.find(SSRC);
462
463 if (it == _csrcCNAMEs.end()) {
464 return -1;
465 }
466 delete it->second;
467 _csrcCNAMEs.erase(it);
468 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000469}
470
471bool
472RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
473{
474/*
475 For audio we use a fix 5 sec interval
476
477 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000478 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
479 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000480
481
482From RFC 3550
483
484 MAX RTCP BW is 5% if the session BW
485 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000486 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000487
488 The RECOMMENDED value for the reduced minimum in seconds is 360
489 divided by the session bandwidth in kilobits/second. This minimum
490 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
491
492 If the participant has not yet sent an RTCP packet (the variable
493 initial is true), the constant Tmin is set to 2.5 seconds, else it
494 is set to 5 seconds.
495
496 The interval between RTCP packets is varied randomly over the
497 range [0.5,1.5] times the calculated interval to avoid unintended
498 synchronization of all participants
499
500 if we send
501 If the participant is a sender (we_sent true), the constant C is
502 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
503 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
504 number of senders.
505
506 if we receive only
507 If we_sent is not true, the constant C is set
508 to the average RTCP packet size divided by 75% of the RTCP
509 bandwidth. The constant n is set to the number of receivers
510 (members - senders). If the number of senders is greater than
511 25%, senders and receivers are treated together.
512
513 reconsideration NOT required for peer-to-peer
514 "timer reconsideration" is
515 employed. This algorithm implements a simple back-off mechanism
516 which causes users to hold back RTCP packet transmission if the
517 group sizes are increasing.
518
519 n = number of members
520 C = avg_size/(rtcpBW/4)
521
522 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
523
524 4. The calculated interval T is set to a number uniformly distributed
525 between 0.5 and 1.5 times the deterministic calculated interval.
526
527 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
528 for the fact that the timer reconsideration algorithm converges to
529 a value of the RTCP bandwidth below the intended average
530*/
531
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000532 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000533
534 CriticalSectionScoped lock(_criticalSectionRTCPSender);
535
niklase@google.com470e71d2011-07-07 08:21:25 +0000536 if(_method == kRtcpOff)
537 {
538 return false;
539 }
540
niklase@google.com470e71d2011-07-07 08:21:25 +0000541 if(!_audio && sendKeyframeBeforeRTP)
542 {
543 // for video key-frames we want to send the RTCP before the large key-frame
544 // if we have a 100 ms margin
545 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
546 }
547
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000548 if(now >= _nextTimeToSendRTCP)
niklase@google.com470e71d2011-07-07 08:21:25 +0000549 {
550 return true;
551
552 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
553 {
554 // wrap
555 return true;
556 }
557 return false;
558}
559
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000560uint32_t
561RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000562{
563 CriticalSectionScoped lock(_criticalSectionRTCPSender);
564
565 lastRTCPTime = _lastRTCPTime[0];
566 return _lastSendReport[0];
567}
568
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000569uint32_t
570RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000571{
572 CriticalSectionScoped lock(_criticalSectionRTCPSender);
573
574 // This is only saved when we are the sender
575 if((_lastSendReport[0] == 0) || (sendReport == 0))
576 {
577 return 0; // will be ignored
578 } else
579 {
580 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
581 {
582 if( _lastSendReport[i] == sendReport)
583 {
584 return _lastRTCPTime[i];
585 }
586 }
587 }
588 return 0;
589}
590
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000591bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
592 int64_t* time_ms) const {
593 CriticalSectionScoped lock(_criticalSectionRTCPSender);
594
595 if (last_xr_rr_.empty()) {
596 return false;
597 }
598 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
599 if (it == last_xr_rr_.end()) {
600 return false;
601 }
602 *time_ms = it->second;
603 return true;
604}
605
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000606void RTCPSender::GetPacketTypeCounter(
607 RtcpPacketTypeCounter* packet_counter) const {
608 CriticalSectionScoped lock(_criticalSectionRTCPSender);
609 *packet_counter = packet_type_counter_;
610}
611
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000612int32_t RTCPSender::AddExternalReportBlock(
613 uint32_t SSRC,
614 const RTCPReportBlock* reportBlock) {
615 CriticalSectionScoped lock(_criticalSectionRTCPSender);
616 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
617}
618
619int32_t RTCPSender::AddReportBlock(
620 uint32_t SSRC,
621 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
622 const RTCPReportBlock* reportBlock) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000623 assert(reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000624
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000625 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000626 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000627 return -1;
628 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000629 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000630 report_blocks->find(SSRC);
631 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000632 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000633 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000634 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000635 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
636 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000637 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000638 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000639}
640
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000641int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000642 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000643
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000644 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000645 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000646
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000647 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000648 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000649 }
650 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000651 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000652 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000653}
654
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000655int32_t RTCPSender::BuildSR(const FeedbackState& feedback_state,
656 uint8_t* rtcpbuffer,
657 int& pos,
658 uint32_t NTPsec,
659 uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000660{
661 // sanity
662 if(pos + 52 >= IP_PACKET_SIZE)
663 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000664 LOG(LS_WARNING) << "Failed to build Sender Report.";
niklase@google.com470e71d2011-07-07 08:21:25 +0000665 return -2;
666 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000667 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000668
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000669 uint32_t posNumberOfReportBlocks = pos;
670 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000671
672 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000673 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000674
675 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
676 {
677 // shift old
678 _lastSendReport[i+1] = _lastSendReport[i];
679 _lastRTCPTime[i+1] =_lastRTCPTime[i];
680 }
681
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000682 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000683 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000684
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000685 // The timestamp of this RTCP packet should be estimated as the timestamp of
686 // the frame being captured at this moment. We are calculating that
687 // timestamp as the last frame's timestamp + the time since the last frame
688 // was captured.
689 {
690 // Needs protection since this method is called on the process thread.
691 CriticalSectionScoped lock(_criticalSectionRTCPSender);
692 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
693 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000694 (feedback_state.frequency_hz / 1000);
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000695 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000696
697 // Add sender data
698 // Save for our length field
699 pos++;
700 pos++;
701
702 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000703 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000704 pos += 4;
705 // NTP
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000706 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000707 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000708 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000709 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000710 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, RTPtime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000711 pos += 4;
712
713 //sender's packet count
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000714 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
715 feedback_state.packet_count_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000716 pos += 4;
717
718 //sender's octet count
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000719 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
720 feedback_state.byte_count_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000721 pos += 4;
722
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000723 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000724 int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
725 numberOfReportBlocks,
726 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000727 if(retVal < 0)
728 {
729 //
730 return retVal ;
731 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000732 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000733 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
734
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000735 uint16_t len = uint16_t((pos/4) -1);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000736 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000737 return 0;
738}
739
740
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000741int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000742 size_t lengthCname = strlen(_CNAME);
743 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000744
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000745 // sanity
746 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000747 LOG(LS_WARNING) << "Failed to build SDEC.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000748 return -2;
749 }
750 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000751
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000752 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000753 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
754 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000755
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000756 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000757 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000758 pos++;
759 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000760
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000761 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000762 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000763 pos += 4;
764
765 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000766 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000767
768 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000769 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000770
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000771 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000772
773 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
774 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000775 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000776
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000777 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000778 // We must have a zero field even if we have an even multiple of 4 bytes
779 if ((pos % 4) == 0) {
780 padding++;
781 rtcpbuffer[pos++]=0;
782 }
783 while ((pos % 4) != 0) {
784 padding++;
785 rtcpbuffer[pos++]=0;
786 }
787 SDESLength += padding;
788
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000789 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000790 _csrcCNAMEs.begin();
791
792 for(; it != _csrcCNAMEs.end(); it++) {
793 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000794 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000795
796 // Add SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000797 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000798 pos += 4;
799
800 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000801 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000802
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000803 size_t length = strlen(cname->name);
804 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000805
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000806 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000807 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000808
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000809 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000810
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000811 pos += length;
812 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000813 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000814
815 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000816 if((pos % 4) == 0){
817 padding++;
818 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000819 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000820 while((pos % 4) != 0){
821 padding++;
822 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000823 }
824 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000825 }
826 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000827 uint16_t buffer_length = (SDESLength / 4) - 1;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000828 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos, buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000829 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000830}
831
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000832int32_t
833RTCPSender::BuildRR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000834 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000835 const uint32_t NTPsec,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000836 const uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000837{
838 // sanity one block
839 if(pos + 32 >= IP_PACKET_SIZE)
840 {
841 return -2;
842 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000843 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000844
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000845 rtcpbuffer[pos++]=(uint8_t)0x80;
846 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000847
848 // Save for our length field
849 pos++;
850 pos++;
851
852 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000853 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000854 pos += 4;
855
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000856 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000857 int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
858 numberOfReportBlocks,
859 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000860 if(retVal < 0)
861 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000862 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000863 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000864 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000865 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
866
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000867 uint16_t len = uint16_t((pos)/4 -1);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000868 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000869 return 0;
870}
871
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000872// From RFC 5450: Transmission Time Offsets in RTP Streams.
873// 0 1 2 3
874// 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
875// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
876// hdr |V=2|P| RC | PT=IJ=195 | length |
877// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
878// | inter-arrival jitter |
879// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
880// . .
881// . .
882// . .
883// | inter-arrival jitter |
884// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
885//
886// If present, this RTCP packet must be placed after a receiver report
887// (inside a compound RTCP packet), and MUST have the same value for RC
888// (reception report count) as the receiver report.
889
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000890int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000891RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000892 uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000893 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000894 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000895{
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000896 if (external_report_blocks_.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000897 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000898 // TODO(andresp): Remove external report blocks since they are not
899 // supported.
900 LOG(LS_ERROR) << "Handling of external report blocks not implemented.";
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000901 return 0;
902 }
903
904 // sanity
905 if(pos + 8 >= IP_PACKET_SIZE)
906 {
907 return -2;
908 }
909 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000910 uint8_t RC = 1;
911 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
912 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000913
914 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000915 rtcpbuffer[pos++]=(uint8_t)0;
916 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000917
918 // Add inter-arrival jitter
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000919 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
920 jitterTransmissionTimeOffset);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000921 pos += 4;
922 return 0;
923}
924
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000925int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000926RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000927{
928 // sanity
929 if(pos + 12 >= IP_PACKET_SIZE)
930 {
931 return -2;
932 }
933 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000934 uint8_t FMT = 1;
935 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
936 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000937
938 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000939 rtcpbuffer[pos++]=(uint8_t)0;
940 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000941
942 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000943 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000944 pos += 4;
945
946 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000947 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000948 pos += 4;
949 return 0;
950}
951
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000952int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000953 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000954 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000955 // sanity
956 if(pos + 20 >= IP_PACKET_SIZE) {
957 return -2;
958 }
959 if (!repeat) {
960 _sequenceNumberFIR++; // do not increase if repetition
961 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000962
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000963 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000964 uint8_t FMT = 4;
965 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
966 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000967
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000968 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000969 rtcpbuffer[pos++] = (uint8_t)0;
970 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000971
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000972 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000973 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000974 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000975
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000976 // RFC 5104 4.3.1.2. Semantics
977 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000978 rtcpbuffer[pos++] = (uint8_t)0;
979 rtcpbuffer[pos++] = (uint8_t)0;
980 rtcpbuffer[pos++] = (uint8_t)0;
981 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000982
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000983 // Additional Feedback Control Information (FCI)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000984 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000985 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000986
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000987 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
988 rtcpbuffer[pos++] = (uint8_t)0;
989 rtcpbuffer[pos++] = (uint8_t)0;
990 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000991 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000992}
993
994/*
995 0 1 2 3
996 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
997 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
998 | First | Number | PictureID |
999 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1000*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001001int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001002RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +00001003{
1004 // sanity
1005 if(pos + 16 >= IP_PACKET_SIZE)
1006 {
1007 return -2;
1008 }
1009 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001010 uint8_t FMT = 2;
1011 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1012 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001013
1014 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001015 rtcpbuffer[pos++]=(uint8_t)0;
1016 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +00001017
1018 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001019 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001020 pos += 4;
1021
1022 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001023 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001024 pos += 4;
1025
1026 // Add first, number & picture ID 6 bits
1027 // first = 0, 13 - bits
1028 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001029 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001030 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, sliField);
niklase@google.com470e71d2011-07-07 08:21:25 +00001031 pos += 4;
1032 return 0;
1033}
1034
1035/*
1036 0 1 2 3
1037 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
1038 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1039 | PB |0| Payload Type| Native RPSI bit string |
1040 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1041 | defined per codec ... | Padding (0) |
1042 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1043*/
1044/*
1045* Note: not generic made for VP8
1046*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001047int32_t
1048RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001049 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001050 const uint64_t pictureID,
1051 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +00001052{
1053 // sanity
1054 if(pos + 24 >= IP_PACKET_SIZE)
1055 {
1056 return -2;
1057 }
1058 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001059 uint8_t FMT = 3;
1060 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1061 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001062
1063 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001064 uint32_t bitsRequired = 7;
1065 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001066 while((pictureID>>bitsRequired) > 0)
1067 {
1068 bitsRequired += 7;
1069 bytesRequired++;
1070 }
1071
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001072 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001073 if(bytesRequired > 6)
1074 {
1075 size = 5;
1076 } else if(bytesRequired > 2)
1077 {
1078 size = 4;
1079 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001080 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001081 rtcpbuffer[pos++]=size;
1082
1083 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001084 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001085 pos += 4;
1086
1087 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001088 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001089 pos += 4;
1090
1091 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001092 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001093 if(paddingBytes == 4)
1094 {
1095 paddingBytes = 0;
1096 }
1097 // add padding length in bits
1098 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1099 pos++;
1100
1101 // add payload type
1102 rtcpbuffer[pos] = payloadType;
1103 pos++;
1104
1105 // add picture ID
1106 for(int i = bytesRequired-1; i > 0; i--)
1107 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001108 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001109 pos++;
1110 }
1111 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001112 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001113 pos++;
1114
1115 // add padding
1116 for(int j = 0; j <paddingBytes; j++)
1117 {
1118 rtcpbuffer[pos] = 0;
1119 pos++;
1120 }
1121 return 0;
1122}
1123
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001124int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001125RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001126{
1127 // sanity
1128 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1129 {
1130 return -2;
1131 }
1132 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001133 uint8_t FMT = 15;
1134 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1135 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001136
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001137 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001138 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1139
1140 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001141 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001142 pos += 4;
1143
1144 // Remote SSRC must be 0
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001145 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, 0);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001146 pos += 4;
1147
1148 rtcpbuffer[pos++]='R';
1149 rtcpbuffer[pos++]='E';
1150 rtcpbuffer[pos++]='M';
1151 rtcpbuffer[pos++]='B';
1152
1153 rtcpbuffer[pos++] = _lengthRembSSRC;
1154 // 6 bit Exp
1155 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001156 uint8_t brExp = 0;
1157 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001158 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001159 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001160 {
1161 brExp = i;
1162 break;
1163 }
1164 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001165 const uint32_t brMantissa = (_rembBitrate >> brExp);
1166 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1167 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1168 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001169
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +00001170 for (int i = 0; i < _lengthRembSSRC; i++)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001171 {
1172 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _rembSSRC[i]);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001173 pos += 4;
1174 }
1175 return 0;
1176}
1177
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001178void
1179RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001180{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001181 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001182 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001183}
1184
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001185int32_t RTCPSender::BuildTMMBR(ModuleRtpRtcpImpl* rtp_rtcp_module,
1186 uint8_t* rtcpbuffer,
1187 int& pos) {
1188 if (rtp_rtcp_module == NULL)
1189 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001190 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1191 // If the sender is an owner of the TMMBN -> send TMMBR
1192 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1193
niklase@google.com470e71d2011-07-07 08:21:25 +00001194 // get current bounding set from RTCP receiver
1195 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001196 // store in candidateSet, allocates one extra slot
1197 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001198
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001199 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1200 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1201 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001202 int32_t lengthOfBoundingSet =
1203 rtp_rtcp_module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001204
1205 if(lengthOfBoundingSet > 0)
1206 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001207 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001208 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001209 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1210 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001211 {
1212 // do not send the same tuple
1213 return 0;
1214 }
1215 }
1216 if(!tmmbrOwner)
1217 {
1218 // use received bounding set as candidate set
1219 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001220 candidateSet->SetEntry(lengthOfBoundingSet,
1221 _tmmbr_Send,
1222 _packetOH_Send,
1223 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001224 int numCandidates = lengthOfBoundingSet+ 1;
1225
1226 // find bounding set
1227 TMMBRSet* boundingSet = NULL;
1228 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1229 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1230 {
1231 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1232 }
1233 if(!tmmbrOwner)
1234 {
1235 // did not enter bounding set, no meaning to send this request
1236 return 0;
1237 }
1238 }
1239 }
1240
1241 if(_tmmbr_Send)
1242 {
1243 // sanity
1244 if(pos + 20 >= IP_PACKET_SIZE)
1245 {
1246 return -2;
1247 }
1248 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001249 uint8_t FMT = 3;
1250 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1251 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001252
1253 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001254 rtcpbuffer[pos++]=(uint8_t)0;
1255 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001256
1257 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001258 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001259 pos += 4;
1260
1261 // RFC 5104 4.2.1.2. Semantics
1262
1263 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001264 rtcpbuffer[pos++]=(uint8_t)0;
1265 rtcpbuffer[pos++]=(uint8_t)0;
1266 rtcpbuffer[pos++]=(uint8_t)0;
1267 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001268
1269 // Additional Feedback Control Information (FCI)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001270 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001271 pos += 4;
1272
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001273 uint32_t bitRate = _tmmbr_Send*1000;
1274 uint32_t mmbrExp = 0;
1275 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001276 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001277 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001278 {
1279 mmbrExp = i;
1280 break;
1281 }
1282 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001283 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001284
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001285 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1286 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1287 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1288 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001289 }
1290 return 0;
1291}
1292
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001293int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001294RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001295{
1296 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1297 if(boundingSet == NULL)
1298 {
1299 return -1;
1300 }
1301 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001302 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001303 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001304 LOG(LS_WARNING) << "Failed to build TMMBN.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001305 return -2;
1306 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001307 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001308 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001309 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1310 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001311
1312 //Add length later
1313 int posLength = pos;
1314 pos++;
1315 pos++;
1316
1317 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001318 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001319 pos += 4;
1320
1321 // RFC 5104 4.2.2.2. Semantics
1322
1323 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001324 rtcpbuffer[pos++]=(uint8_t)0;
1325 rtcpbuffer[pos++]=(uint8_t)0;
1326 rtcpbuffer[pos++]=(uint8_t)0;
1327 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001328
1329 // Additional Feedback Control Information (FCI)
1330 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001331 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001332 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001333 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001334 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001335 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001336 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, tmmbrSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001337 pos += 4;
1338
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001339 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1340 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001341 for(int i=0; i<64; i++)
1342 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001343 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001344 {
1345 mmbrExp = i;
1346 break;
1347 }
1348 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001349 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1350 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001351
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001352 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1353 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1354 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1355 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001356 numBoundingSet++;
1357 }
1358 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001359 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1360 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1361 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001362 return 0;
1363}
1364
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001365int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001366RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001367{
1368 // sanity
1369 if(_appData == NULL)
1370 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001371 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001372 return -1;
1373 }
1374 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1375 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001376 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001377 return -2;
1378 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001379 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001380
1381 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001382 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001383
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001384 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1385 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1386 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001387
1388 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001389 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001390 pos += 4;
1391
1392 // Add our application name
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001393 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _appName);
niklase@google.com470e71d2011-07-07 08:21:25 +00001394 pos += 4;
1395
1396 // Add the data
1397 memcpy(rtcpbuffer +pos, _appData,_appLength);
1398 pos += _appLength;
1399 return 0;
1400}
1401
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001402int32_t
1403RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001404 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001405 const int32_t nackSize,
1406 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001407 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001408{
1409 // sanity
1410 if(pos + 16 >= IP_PACKET_SIZE)
1411 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001412 LOG(LS_WARNING) << "Failed to build NACK.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001413 return -2;
1414 }
1415
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001416 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001417 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001418 uint8_t FMT = 1;
1419 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1420 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001421
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001422 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001423 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001424 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001425
1426 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001427 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001428 pos += 4;
1429
1430 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001431 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001432 pos += 4;
1433
edjee@google.com79b02892013-04-04 19:43:34 +00001434 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001435 // Build NACK bitmasks and write them to the RTCP message.
1436 // The nack list should be sorted and not contain duplicates if one
1437 // wants to build the smallest rtcp nack packet.
1438 int numOfNackFields = 0;
1439 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1440 (IP_PACKET_SIZE - pos) / 4);
1441 int i = 0;
1442 while (i < nackSize && numOfNackFields < maxNackFields) {
1443 stringBuilder.PushNACK(nackList[i]);
1444 uint16_t nack = nackList[i++];
1445 uint16_t bitmask = 0;
1446 while (i < nackSize) {
1447 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1448 if (shift >= 0 && shift <= 15) {
1449 stringBuilder.PushNACK(nackList[i]);
1450 bitmask |= (1 << shift);
1451 ++i;
1452 } else {
1453 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001454 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001455 }
1456 // Write the sequence number and the bitmask to the packet.
1457 assert(pos + 4 < IP_PACKET_SIZE);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001458 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001459 pos += 2;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001460 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001461 pos += 2;
1462 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001463 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001464 if (i != nackSize) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001465 LOG(LS_WARNING) << "Nack list to large for one packet.";
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001466 }
1467 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001468 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001469 return 0;
1470}
1471
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001472int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001473RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001474{
1475 // sanity
1476 if(pos + 8 >= IP_PACKET_SIZE)
1477 {
1478 return -2;
1479 }
1480 if(_includeCSRCs)
1481 {
1482 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001483 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1484 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001485
1486 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001487 rtcpbuffer[pos++]=(uint8_t)0;
1488 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001489
1490 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001491 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001492 pos += 4;
1493
1494 // add CSRCs
1495 for(int i = 0; i < _CSRCs; i++)
1496 {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001497 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _CSRC[i]);
niklase@google.com470e71d2011-07-07 08:21:25 +00001498 pos += 4;
1499 }
1500 } else
1501 {
1502 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001503 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1504 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001505
1506 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001507 rtcpbuffer[pos++]=(uint8_t)0;
1508 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001509
1510 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001511 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001512 pos += 4;
1513 }
1514 return 0;
1515}
1516
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001517int32_t RTCPSender::BuildReceiverReferenceTime(uint8_t* buffer,
1518 int& pos,
1519 uint32_t ntp_sec,
1520 uint32_t ntp_frac) {
1521 const int kRrTimeBlockLength = 20;
1522 if (pos + kRrTimeBlockLength >= IP_PACKET_SIZE) {
1523 return -2;
1524 }
1525
1526 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) {
1527 last_xr_rr_.erase(last_xr_rr_.begin());
1528 }
1529 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
1530 RTCPUtility::MidNtp(ntp_sec, ntp_frac),
1531 Clock::NtpToMs(ntp_sec, ntp_frac)));
1532
1533 // Add XR header.
1534 buffer[pos++] = 0x80;
1535 buffer[pos++] = 207;
1536 buffer[pos++] = 0; // XR packet length.
1537 buffer[pos++] = 4; // XR packet length.
1538
1539 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001540 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001541 pos += 4;
1542
1543 // 0 1 2 3
1544 // 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
1545 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1546 // | BT=4 | reserved | block length = 2 |
1547 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1548 // | NTP timestamp, most significant word |
1549 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1550 // | NTP timestamp, least significant word |
1551 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1552
1553 // Add Receiver Reference Time Report block.
1554 buffer[pos++] = 4; // BT.
1555 buffer[pos++] = 0; // Reserved.
1556 buffer[pos++] = 0; // Block length.
1557 buffer[pos++] = 2; // Block length.
1558
1559 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001560 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_sec);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001561 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001562 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001563 pos += 4;
1564
1565 return 0;
1566}
1567
1568int32_t RTCPSender::BuildDlrr(uint8_t* buffer,
1569 int& pos,
1570 const RtcpReceiveTimeInfo& info) {
1571 const int kDlrrBlockLength = 24;
1572 if (pos + kDlrrBlockLength >= IP_PACKET_SIZE) {
1573 return -2;
1574 }
1575
1576 // Add XR header.
1577 buffer[pos++] = 0x80;
1578 buffer[pos++] = 207;
1579 buffer[pos++] = 0; // XR packet length.
1580 buffer[pos++] = 5; // XR packet length.
1581
1582 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001583 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001584 pos += 4;
1585
1586 // 0 1 2 3
1587 // 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
1588 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1589 // | BT=5 | reserved | block length |
1590 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1591 // | SSRC_1 (SSRC of first receiver) | sub-
1592 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1593 // | last RR (LRR) | 1
1594 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1595 // | delay since last RR (DLRR) |
1596 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1597 // | SSRC_2 (SSRC of second receiver) | sub-
1598 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1599 // : ... : 2
1600
1601 // Add DLRR sub block.
1602 buffer[pos++] = 5; // BT.
1603 buffer[pos++] = 0; // Reserved.
1604 buffer[pos++] = 0; // Block length.
1605 buffer[pos++] = 3; // Block length.
1606
1607 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001608 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.sourceSSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001609 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001610 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.lastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001611 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001612 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.delaySinceLastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001613 pos += 4;
1614
1615 return 0;
1616}
1617
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001618int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001619RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001620{
1621 // sanity
1622 if(pos + 44 >= IP_PACKET_SIZE)
1623 {
1624 return -2;
1625 }
1626
1627 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001628 rtcpbuffer[pos++]=(uint8_t)0x80;
1629 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001630
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001631 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001632
1633 // handle length later on
1634 pos++;
1635 pos++;
1636
1637 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001638 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001639 pos += 4;
1640
1641 // Add a VoIP metrics block
1642 rtcpbuffer[pos++]=7;
1643 rtcpbuffer[pos++]=0;
1644 rtcpbuffer[pos++]=0;
1645 rtcpbuffer[pos++]=8;
1646
1647 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001648 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001649 pos += 4;
1650
1651 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1652 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1653 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1654 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1655
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001656 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1657 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1658 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1659 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001660
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001661 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1662 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1663 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1664 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001665
1666 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1667 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1668 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1669 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1670
1671 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1672 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1673 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1674 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1675
1676 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1677 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001678 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1679 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001680
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001681 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1682 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1683 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1684 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001685
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001686 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1687 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001688 return 0;
1689}
1690
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001691int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
1692 uint32_t packetTypeFlags,
1693 int32_t nackSize,
1694 const uint16_t* nackList,
1695 bool repeat,
1696 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001697 {
1698 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1699 if(_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001700 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001701 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001702 return -1;
1703 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001704 }
1705 uint8_t rtcp_buffer[IP_PACKET_SIZE];
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001706 int rtcp_length = PrepareRTCP(feedback_state,
1707 packetTypeFlags,
1708 nackSize,
1709 nackList,
1710 repeat,
1711 pictureID,
1712 rtcp_buffer,
1713 IP_PACKET_SIZE);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001714 if (rtcp_length < 0) {
1715 return -1;
1716 }
1717 // Sanity don't send empty packets.
1718 if (rtcp_length == 0)
1719 {
1720 return -1;
1721 }
1722 return SendToNetwork(rtcp_buffer, static_cast<uint16_t>(rtcp_length));
1723}
1724
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001725int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
1726 uint32_t packetTypeFlags,
1727 int32_t nackSize,
1728 const uint16_t* nackList,
1729 bool repeat,
1730 uint64_t pictureID,
1731 uint8_t* rtcp_buffer,
1732 int buffer_size) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001733 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1734 // Collect the received information.
1735 uint32_t NTPsec = 0;
1736 uint32_t NTPfrac = 0;
1737 uint32_t jitterTransmissionOffset = 0;
1738 int position = 0;
1739
1740 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1741
1742 if(_TMMBR ) // Attach TMMBR to send and receive reports.
1743 {
1744 rtcpPacketTypeFlags |= kRtcpTmmbr;
1745 }
1746 if(_appSend)
1747 {
1748 rtcpPacketTypeFlags |= kRtcpApp;
1749 _appSend = false;
1750 }
1751 if(_REMB && _sendREMB)
1752 {
1753 // Always attach REMB to SR if that is configured. Note that REMB is
1754 // only sent on one of the RTP modules in the REMB group.
1755 rtcpPacketTypeFlags |= kRtcpRemb;
1756 }
1757 if(_xrSendVoIPMetric)
1758 {
1759 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1760 _xrSendVoIPMetric = false;
1761 }
1762 if(_sendTMMBN) // Set when having received a TMMBR.
1763 {
1764 rtcpPacketTypeFlags |= kRtcpTmmbn;
1765 _sendTMMBN = false;
1766 }
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001767 if (rtcpPacketTypeFlags & kRtcpReport)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001768 {
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001769 if (xrSendReceiverReferenceTimeEnabled_ && !_sending)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001770 {
1771 rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
1772 }
1773 if (feedback_state.has_last_xr_rr)
1774 {
1775 rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
1776 }
1777 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001778 if(_method == kRtcpCompound)
1779 {
1780 if(_sending)
1781 {
1782 rtcpPacketTypeFlags |= kRtcpSr;
1783 } else
1784 {
1785 rtcpPacketTypeFlags |= kRtcpRr;
1786 }
1787 } else if(_method == kRtcpNonCompound)
1788 {
1789 if(rtcpPacketTypeFlags & kRtcpReport)
1790 {
1791 if(_sending)
1792 {
1793 rtcpPacketTypeFlags |= kRtcpSr;
1794 } else
1795 {
1796 rtcpPacketTypeFlags |= kRtcpRr;
1797 }
1798 }
1799 }
1800 if( rtcpPacketTypeFlags & kRtcpRr ||
1801 rtcpPacketTypeFlags & kRtcpSr)
1802 {
1803 // generate next time to send a RTCP report
1804 // seeded from RTP constructor
1805 int32_t random = rand() % 1000;
1806 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1807
1808 if(_audio)
1809 {
1810 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1811 (RTCP_INTERVAL_AUDIO_MS*random/1000);
1812 }else
1813 {
1814 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1815 if(_sending)
1816 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001817 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1818 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1819 if (send_bitrate_kbit != 0)
1820 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001821 }
1822 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1823 {
1824 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1825 }
1826 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1827 }
1828 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1829 }
1830
1831 // If the data does not fit in the packet we fill it as much as possible.
1832 int32_t buildVal = 0;
1833
1834 // We need to send our NTP even if we haven't received any reports.
1835 _clock->CurrentNtp(NTPsec, NTPfrac);
1836 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1837 StatisticianMap statisticians =
1838 receive_statistics_->GetActiveStatisticians();
1839 if (!statisticians.empty()) {
1840 StatisticianMap::const_iterator it;
1841 int i;
1842 for (it = statisticians.begin(), i = 0; it != statisticians.end();
1843 ++it, ++i) {
1844 RTCPReportBlock report_block;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001845 if (PrepareReport(
1846 feedback_state, it->second, &report_block, &NTPsec, &NTPfrac))
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001847 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1848 }
1849 if (_IJ && !statisticians.empty()) {
1850 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1851 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001852 }
1853 }
1854
1855 if(rtcpPacketTypeFlags & kRtcpSr)
1856 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001857 buildVal = BuildSR(feedback_state, rtcp_buffer, position, NTPsec, NTPfrac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001858 if (buildVal == -1) {
1859 return -1;
1860 } else if (buildVal == -2) {
1861 return position;
1862 }
1863 buildVal = BuildSDEC(rtcp_buffer, position);
1864 if (buildVal == -1) {
1865 return -1;
1866 } else if (buildVal == -2) {
1867 return position;
1868 }
1869 }else if(rtcpPacketTypeFlags & kRtcpRr)
1870 {
1871 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1872 if (buildVal == -1) {
1873 return -1;
1874 } else if (buildVal == -2) {
1875 return position;
1876 }
1877 // only of set
1878 if(_CNAME[0] != 0)
1879 {
1880 buildVal = BuildSDEC(rtcp_buffer, position);
1881 if (buildVal == -1) {
1882 return -1;
1883 }
1884 }
1885 }
1886 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1887 {
1888 // If present, this RTCP packet must be placed after a
1889 // receiver report.
1890 buildVal = BuildExtendedJitterReport(rtcp_buffer,
1891 position,
1892 jitterTransmissionOffset);
1893 if (buildVal == -1) {
1894 return -1;
1895 } else if (buildVal == -2) {
1896 return position;
1897 }
1898 }
1899 if(rtcpPacketTypeFlags & kRtcpPli)
1900 {
1901 buildVal = BuildPLI(rtcp_buffer, position);
1902 if (buildVal == -1) {
1903 return -1;
1904 } else if (buildVal == -2) {
1905 return position;
1906 }
1907 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001908 ++packet_type_counter_.pli_packets;
1909 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC,
1910 packet_type_counter_.pli_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001911 }
1912 if(rtcpPacketTypeFlags & kRtcpFir)
1913 {
1914 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1915 if (buildVal == -1) {
1916 return -1;
1917 } else if (buildVal == -2) {
1918 return position;
1919 }
1920 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001921 ++packet_type_counter_.fir_packets;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001922 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001923 packet_type_counter_.fir_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001924 }
1925 if(rtcpPacketTypeFlags & kRtcpSli)
1926 {
1927 buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1928 if (buildVal == -1) {
1929 return -1;
1930 } else if (buildVal == -2) {
1931 return position;
1932 }
1933 }
1934 if(rtcpPacketTypeFlags & kRtcpRpsi)
1935 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001936 const int8_t payloadType = feedback_state.send_payload_type;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001937 if (payloadType == -1) {
1938 return -1;
1939 }
1940 buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1941 (uint8_t)payloadType);
1942 if (buildVal == -1) {
1943 return -1;
1944 } else if (buildVal == -2) {
1945 return position;
1946 }
1947 }
1948 if(rtcpPacketTypeFlags & kRtcpRemb)
1949 {
1950 buildVal = BuildREMB(rtcp_buffer, position);
1951 if (buildVal == -1) {
1952 return -1;
1953 } else if (buildVal == -2) {
1954 return position;
1955 }
1956 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1957 }
1958 if(rtcpPacketTypeFlags & kRtcpBye)
1959 {
1960 buildVal = BuildBYE(rtcp_buffer, position);
1961 if (buildVal == -1) {
1962 return -1;
1963 } else if (buildVal == -2) {
1964 return position;
1965 }
1966 }
1967 if(rtcpPacketTypeFlags & kRtcpApp)
1968 {
1969 buildVal = BuildAPP(rtcp_buffer, position);
1970 if (buildVal == -1) {
1971 return -1;
1972 } else if (buildVal == -2) {
1973 return position;
1974 }
1975 }
1976 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1977 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001978 buildVal = BuildTMMBR(feedback_state.module, rtcp_buffer, position);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001979 if (buildVal == -1) {
1980 return -1;
1981 } else if (buildVal == -2) {
1982 return position;
1983 }
1984 }
1985 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1986 {
1987 buildVal = BuildTMMBN(rtcp_buffer, position);
1988 if (buildVal == -1) {
1989 return -1;
1990 } else if (buildVal == -2) {
1991 return position;
1992 }
1993 }
1994 if(rtcpPacketTypeFlags & kRtcpNack)
1995 {
1996 std::string nackString;
1997 buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
1998 &nackString);
1999 if (buildVal == -1) {
2000 return -1;
2001 } else if (buildVal == -2) {
2002 return position;
2003 }
2004 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
2005 "nacks", TRACE_STR_COPY(nackString.c_str()));
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00002006 ++packet_type_counter_.nack_packets;
2007 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC,
2008 packet_type_counter_.nack_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002009 }
2010 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
2011 {
2012 buildVal = BuildVoIPMetric(rtcp_buffer, position);
2013 if (buildVal == -1) {
2014 return -1;
2015 } else if (buildVal == -2) {
2016 return position;
2017 }
2018 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002019 if (rtcpPacketTypeFlags & kRtcpXrReceiverReferenceTime)
2020 {
2021 buildVal = BuildReceiverReferenceTime(rtcp_buffer,
2022 position,
2023 NTPsec,
2024 NTPfrac);
2025 if (buildVal == -1) {
2026 return -1;
2027 } else if (buildVal == -2) {
2028 return position;
2029 }
2030 }
2031 if (rtcpPacketTypeFlags & kRtcpXrDlrrReportBlock)
2032 {
2033 buildVal = BuildDlrr(rtcp_buffer, position, feedback_state.last_xr_rr);
2034 if (buildVal == -1) {
2035 return -1;
2036 } else if (buildVal == -2) {
2037 return position;
2038 }
2039 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002040 return position;
2041}
2042
2043bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
2044 return Status() == kRtcpCompound ||
2045 (rtcp_packet_type & kRtcpReport) ||
2046 (rtcp_packet_type & kRtcpSr) ||
2047 (rtcp_packet_type & kRtcpRr);
2048}
2049
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002050bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
2051 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002052 RTCPReportBlock* report_block,
2053 uint32_t* ntp_secs, uint32_t* ntp_frac) {
2054 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00002055 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002056 if (!statistician->GetStatistics(&stats, true))
2057 return false;
2058 report_block->fractionLost = stats.fraction_lost;
2059 report_block->cumulativeLost = stats.cumulative_lost;
2060 report_block->extendedHighSeqNum =
2061 stats.extended_max_sequence_number;
2062 report_block->jitter = stats.jitter;
2063
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002064 // get our NTP as late as possible to avoid a race
2065 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
2066
2067 // Delay since last received report
2068 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002069 if ((feedback_state.last_rr_ntp_secs != 0) ||
2070 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002071 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
2072 uint32_t now=*ntp_secs&0x0000FFFF;
2073 now <<=16;
2074 now += (*ntp_frac&0xffff0000)>>16;
2075
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002076 uint32_t receiveTime = feedback_state.last_rr_ntp_secs&0x0000FFFF;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002077 receiveTime <<=16;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002078 receiveTime += (feedback_state.last_rr_ntp_frac&0xffff0000)>>16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002079
2080 delaySinceLastReceivedSR = now-receiveTime;
2081 }
2082 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002083 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002084 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00002085}
2086
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002087int32_t
2088RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
2089 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002090{
2091 CriticalSectionScoped lock(_criticalSectionTransport);
2092 if(_cbTransport)
2093 {
2094 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
2095 {
2096 return 0;
2097 }
2098 }
2099 return -1;
2100}
2101
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002102int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002103RTCPSender::SetCSRCStatus(const bool include)
2104{
2105 _includeCSRCs = include;
2106 return 0;
2107}
2108
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002109int32_t
2110RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
2111 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00002112{
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002113 assert(arrLength <= kRtpCsrcSize);
niklase@google.com470e71d2011-07-07 08:21:25 +00002114 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2115
2116 for(int i = 0; i < arrLength;i++)
2117 {
2118 _CSRC[i] = arrOfCSRC[i];
2119 }
2120 _CSRCs = arrLength;
2121 return 0;
2122}
2123
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002124int32_t
2125RTCPSender::SetApplicationSpecificData(const uint8_t subType,
2126 const uint32_t name,
2127 const uint8_t* data,
2128 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002129{
2130 if(length %4 != 0)
2131 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002132 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
niklase@google.com470e71d2011-07-07 08:21:25 +00002133 return -1;
2134 }
2135 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2136
2137 if(_appData)
2138 {
2139 delete [] _appData;
2140 }
2141
2142 _appSend = true;
2143 _appSubType = subType;
2144 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002145 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002146 _appLength = length;
2147 memcpy(_appData, data, length);
2148 return 0;
2149}
2150
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002151int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002152RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2153{
2154 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2155 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2156
2157 _xrSendVoIPMetric = true;
2158 return 0;
2159}
2160
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002161void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
2162 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2163 xrSendReceiverReferenceTimeEnabled_ = enable;
2164}
2165
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00002166bool RTCPSender::RtcpXrReceiverReferenceTime() const {
2167 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2168 return xrSendReceiverReferenceTimeEnabled_;
2169}
2170
niklase@google.com470e71d2011-07-07 08:21:25 +00002171// called under critsect _criticalSectionRTCPSender
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002172int32_t RTCPSender::WriteAllReportBlocksToBuffer(
2173 uint8_t* rtcpbuffer,
2174 int pos,
2175 uint8_t& numberOfReportBlocks,
2176 const uint32_t NTPsec,
2177 const uint32_t NTPfrac) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002178 numberOfReportBlocks = external_report_blocks_.size();
2179 numberOfReportBlocks += internal_report_blocks_.size();
2180 if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002181 LOG(LS_WARNING) << "Can't fit all report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002182 return -1;
2183 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002184 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2185 while (!internal_report_blocks_.empty()) {
2186 delete internal_report_blocks_.begin()->second;
2187 internal_report_blocks_.erase(internal_report_blocks_.begin());
2188 }
2189 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2190 return pos;
2191}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002192
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002193int32_t RTCPSender::WriteReportBlocksToBuffer(
2194 uint8_t* rtcpbuffer,
2195 int32_t position,
2196 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2197 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2198 report_blocks.begin();
2199 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002200 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002201 RTCPReportBlock* reportBlock = it->second;
2202 if (reportBlock) {
2203 // Remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002204 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position, remoteSSRC);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002205 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002206
2207 // fraction lost
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002208 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002209
2210 // cumulative loss
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002211 RtpUtility::AssignUWord24ToBuffer(rtcpbuffer + position,
2212 reportBlock->cumulativeLost);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002213 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002214
2215 // extended highest seq_no, contain the highest sequence number received
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002216 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2217 reportBlock->extendedHighSeqNum);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002218 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002219
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002220 // Jitter
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002221 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2222 reportBlock->jitter);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002223 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002224
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002225 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2226 reportBlock->lastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002227 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002228
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002229 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2230 reportBlock->delaySinceLastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002231 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002232 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002233 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002234 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00002235}
2236
2237// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002238int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002239RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002240 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002241{
2242 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2243
2244 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2245 {
2246 _sendTMMBN = true;
2247 return 0;
2248 }
2249 return -1;
2250}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002251} // namespace webrtc