blob: afe8019558450db7cdf33a83e0196c2925d22305 [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()
69 : send_payload_type(0),
70 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000071 packets_sent(0),
72 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000073 send_bitrate(0),
74 last_rr_ntp_secs(0),
75 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000076 remote_sr(0),
77 has_last_xr_rr(false) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000078
pbos@webrtc.org2f446732013-04-08 11:08:41 +000079RTCPSender::RTCPSender(const int32_t id,
niklase@google.com470e71d2011-07-07 08:21:25 +000080 const bool audio,
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000081 Clock* clock,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000082 ReceiveStatistics* receive_statistics) :
niklase@google.com470e71d2011-07-07 08:21:25 +000083 _id(id),
84 _audio(audio),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000085 _clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000086 _method(kRtcpOff),
henrike@webrtc.org65573f22011-12-13 19:17:27 +000087 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000088 _cbTransport(NULL),
89
henrike@webrtc.org65573f22011-12-13 19:17:27 +000090 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000091 _usingNack(false),
92 _sending(false),
93 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000094 _REMB(false),
95 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000096 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +000097 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000098 _nextTimeToSendRTCP(0),
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000099 start_timestamp_(0),
100 last_rtp_timestamp_(0),
101 last_frame_capture_time_ms_(-1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000102 _SSRC(0),
103 _remoteSSRC(0),
104 _CNAME(),
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000105 receive_statistics_(receive_statistics),
106 internal_report_blocks_(),
107 external_report_blocks_(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000108 _csrcCNAMEs(),
109
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000110 _cameraDelayMS(0),
111
niklase@google.com470e71d2011-07-07 08:21:25 +0000112 _lastSendReport(),
113 _lastRTCPTime(),
114
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000115 last_xr_rr_(),
116
niklase@google.com470e71d2011-07-07 08:21:25 +0000117 _CSRCs(0),
118 _CSRC(),
119 _includeCSRCs(true),
120
121 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000122
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000123 _lengthRembSSRC(0),
124 _sizeRembSSRC(0),
125 _rembSSRC(NULL),
126 _rembBitrate(0),
127
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000128 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000129 _tmmbr_Send(0),
130 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000131
132 _appSend(false),
133 _appSubType(0),
134 _appName(),
135 _appData(NULL),
136 _appLength(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000137
138 xrSendReceiverReferenceTimeEnabled_(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000139 _xrSendVoIPMetric(false),
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000140 _xrVoIPMetric()
niklase@google.com470e71d2011-07-07 08:21:25 +0000141{
142 memset(_CNAME, 0, sizeof(_CNAME));
143 memset(_lastSendReport, 0, sizeof(_lastSendReport));
144 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
niklase@google.com470e71d2011-07-07 08:21:25 +0000145}
146
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000147RTCPSender::~RTCPSender() {
148 delete [] _rembSSRC;
149 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000150
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000151 while (!internal_report_blocks_.empty()) {
152 delete internal_report_blocks_.begin()->second;
153 internal_report_blocks_.erase(internal_report_blocks_.begin());
154 }
155 while (!external_report_blocks_.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000156 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000157 external_report_blocks_.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000158 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000159 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000160 }
161 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000162 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000163 _csrcCNAMEs.begin();
164 delete it->second;
165 _csrcCNAMEs.erase(it);
166 }
167 delete _criticalSectionTransport;
168 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000169}
170
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000171int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000172RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
173{
174 CriticalSectionScoped lock(_criticalSectionTransport);
175 _cbTransport = outgoingTransport;
176 return 0;
177}
178
179RTCPMethod
180RTCPSender::Status() const
181{
182 CriticalSectionScoped lock(_criticalSectionRTCPSender);
183 return _method;
184}
185
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000186int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000187RTCPSender::SetRTCPStatus(const RTCPMethod method)
188{
189 CriticalSectionScoped lock(_criticalSectionRTCPSender);
190 if(method != kRtcpOff)
191 {
192 if(_audio)
193 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000194 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000195 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000196 } else
197 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000198 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000199 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000200 }
201 }
202 _method = method;
203 return 0;
204}
205
206bool
207RTCPSender::Sending() const
208{
209 CriticalSectionScoped lock(_criticalSectionRTCPSender);
210 return _sending;
211}
212
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000213int32_t
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000214RTCPSender::SetSendingStatus(const FeedbackState& feedback_state, bool sending)
niklase@google.com470e71d2011-07-07 08:21:25 +0000215{
216 bool sendRTCPBye = false;
217 {
218 CriticalSectionScoped lock(_criticalSectionRTCPSender);
219
220 if(_method != kRtcpOff)
221 {
222 if(sending == false && _sending == true)
223 {
224 // Trigger RTCP bye
225 sendRTCPBye = true;
226 }
227 }
228 _sending = sending;
229 }
230 if(sendRTCPBye)
231 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000232 return SendRTCP(feedback_state, kRtcpBye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000233 }
234 return 0;
235}
236
237bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000238RTCPSender::REMB() const
239{
240 CriticalSectionScoped lock(_criticalSectionRTCPSender);
241 return _REMB;
242}
243
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000244int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000245RTCPSender::SetREMBStatus(const bool enable)
246{
247 CriticalSectionScoped lock(_criticalSectionRTCPSender);
248 _REMB = enable;
249 return 0;
250}
251
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000252int32_t
253RTCPSender::SetREMBData(const uint32_t bitrate,
254 const uint8_t numberOfSSRC,
255 const uint32_t* SSRC)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000256{
257 CriticalSectionScoped lock(_criticalSectionRTCPSender);
258 _rembBitrate = bitrate;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000259
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000260 if(_sizeRembSSRC < numberOfSSRC)
261 {
262 delete [] _rembSSRC;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000263 _rembSSRC = new uint32_t[numberOfSSRC];
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000264 _sizeRembSSRC = numberOfSSRC;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000265 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000266
267 _lengthRembSSRC = numberOfSSRC;
268 for (int i = 0; i < numberOfSSRC; i++)
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000269 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000270 _rembSSRC[i] = SSRC[i];
271 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000272 _sendREMB = true;
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000273 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
274 // throttled by the caller.
275 _nextTimeToSendRTCP = _clock->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000276 return 0;
277}
278
279bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000280RTCPSender::TMMBR() const
281{
282 CriticalSectionScoped lock(_criticalSectionRTCPSender);
283 return _TMMBR;
284}
285
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000286int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000287RTCPSender::SetTMMBRStatus(const bool enable)
288{
289 CriticalSectionScoped lock(_criticalSectionRTCPSender);
290 _TMMBR = enable;
291 return 0;
292}
293
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000294bool
295RTCPSender::IJ() const
296{
297 CriticalSectionScoped lock(_criticalSectionRTCPSender);
298 return _IJ;
299}
300
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000301int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000302RTCPSender::SetIJStatus(const bool enable)
303{
304 CriticalSectionScoped lock(_criticalSectionRTCPSender);
305 _IJ = enable;
306 return 0;
307}
308
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000309void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
pbos@webrtc.org180e5162014-07-11 15:36:26 +0000310 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000311 start_timestamp_ = start_timestamp;
312}
313
314void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
315 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000316 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000317 last_rtp_timestamp_ = rtp_timestamp;
318 if (capture_time_ms < 0) {
319 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000320 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000321 } else {
322 last_frame_capture_time_ms_ = capture_time_ms;
323 }
324}
325
niklase@google.com470e71d2011-07-07 08:21:25 +0000326void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000327RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000328{
329 CriticalSectionScoped lock(_criticalSectionRTCPSender);
330
331 if(_SSRC != 0)
332 {
333 // not first SetSSRC, probably due to a collision
334 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000335 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000336 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000337 }
338 _SSRC = ssrc;
339}
340
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000341void RTCPSender::SetRemoteSSRC(uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000342{
343 CriticalSectionScoped lock(_criticalSectionRTCPSender);
344 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000345}
346
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000347int32_t
348RTCPSender::SetCameraDelay(const int32_t delayMS)
349{
350 CriticalSectionScoped lock(_criticalSectionRTCPSender);
351 if(delayMS > 1000 || delayMS < -1000)
352 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000353 LOG(LS_WARNING) << "Delay can't be larger than 1 second: "
354 << delayMS << " ms";
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000355 return -1;
356 }
357 _cameraDelayMS = delayMS;
358 return 0;
359}
360
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000361int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000362 if (!cName)
363 return -1;
364
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000365 CriticalSectionScoped lock(_criticalSectionRTCPSender);
366 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
367 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
368 return 0;
369}
370
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000371int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
372 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000373 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000374 CriticalSectionScoped lock(_criticalSectionRTCPSender);
375 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
376 return -1;
377 }
378 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000379 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
380 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000381 _csrcCNAMEs[SSRC] = ptr;
382 return 0;
383}
384
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000385int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000386 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000387 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000388 _csrcCNAMEs.find(SSRC);
389
390 if (it == _csrcCNAMEs.end()) {
391 return -1;
392 }
393 delete it->second;
394 _csrcCNAMEs.erase(it);
395 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000396}
397
398bool
399RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
400{
401/*
402 For audio we use a fix 5 sec interval
403
404 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000405 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
406 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
408
409From RFC 3550
410
411 MAX RTCP BW is 5% if the session BW
412 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000413 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000414
415 The RECOMMENDED value for the reduced minimum in seconds is 360
416 divided by the session bandwidth in kilobits/second. This minimum
417 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
418
419 If the participant has not yet sent an RTCP packet (the variable
420 initial is true), the constant Tmin is set to 2.5 seconds, else it
421 is set to 5 seconds.
422
423 The interval between RTCP packets is varied randomly over the
424 range [0.5,1.5] times the calculated interval to avoid unintended
425 synchronization of all participants
426
427 if we send
428 If the participant is a sender (we_sent true), the constant C is
429 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
430 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
431 number of senders.
432
433 if we receive only
434 If we_sent is not true, the constant C is set
435 to the average RTCP packet size divided by 75% of the RTCP
436 bandwidth. The constant n is set to the number of receivers
437 (members - senders). If the number of senders is greater than
438 25%, senders and receivers are treated together.
439
440 reconsideration NOT required for peer-to-peer
441 "timer reconsideration" is
442 employed. This algorithm implements a simple back-off mechanism
443 which causes users to hold back RTCP packet transmission if the
444 group sizes are increasing.
445
446 n = number of members
447 C = avg_size/(rtcpBW/4)
448
449 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
450
451 4. The calculated interval T is set to a number uniformly distributed
452 between 0.5 and 1.5 times the deterministic calculated interval.
453
454 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
455 for the fact that the timer reconsideration algorithm converges to
456 a value of the RTCP bandwidth below the intended average
457*/
458
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000459 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000460
461 CriticalSectionScoped lock(_criticalSectionRTCPSender);
462
niklase@google.com470e71d2011-07-07 08:21:25 +0000463 if(_method == kRtcpOff)
464 {
465 return false;
466 }
467
niklase@google.com470e71d2011-07-07 08:21:25 +0000468 if(!_audio && sendKeyframeBeforeRTP)
469 {
470 // for video key-frames we want to send the RTCP before the large key-frame
471 // if we have a 100 ms margin
472 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
473 }
474
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000475 if(now >= _nextTimeToSendRTCP)
niklase@google.com470e71d2011-07-07 08:21:25 +0000476 {
477 return true;
478
479 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
480 {
481 // wrap
482 return true;
483 }
484 return false;
485}
486
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000487uint32_t
488RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000489{
490 CriticalSectionScoped lock(_criticalSectionRTCPSender);
491
492 lastRTCPTime = _lastRTCPTime[0];
493 return _lastSendReport[0];
494}
495
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000496uint32_t
497RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000498{
499 CriticalSectionScoped lock(_criticalSectionRTCPSender);
500
501 // This is only saved when we are the sender
502 if((_lastSendReport[0] == 0) || (sendReport == 0))
503 {
504 return 0; // will be ignored
505 } else
506 {
507 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
508 {
509 if( _lastSendReport[i] == sendReport)
510 {
511 return _lastRTCPTime[i];
512 }
513 }
514 }
515 return 0;
516}
517
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000518bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
519 int64_t* time_ms) const {
520 CriticalSectionScoped lock(_criticalSectionRTCPSender);
521
522 if (last_xr_rr_.empty()) {
523 return false;
524 }
525 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
526 if (it == last_xr_rr_.end()) {
527 return false;
528 }
529 *time_ms = it->second;
530 return true;
531}
532
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000533void RTCPSender::GetPacketTypeCounter(
534 RtcpPacketTypeCounter* packet_counter) const {
535 CriticalSectionScoped lock(_criticalSectionRTCPSender);
536 *packet_counter = packet_type_counter_;
537}
538
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000539int32_t RTCPSender::AddExternalReportBlock(
540 uint32_t SSRC,
541 const RTCPReportBlock* reportBlock) {
542 CriticalSectionScoped lock(_criticalSectionRTCPSender);
543 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
544}
545
546int32_t RTCPSender::AddReportBlock(
547 uint32_t SSRC,
548 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
549 const RTCPReportBlock* reportBlock) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000550 assert(reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000551
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000552 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000553 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000554 return -1;
555 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000556 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000557 report_blocks->find(SSRC);
558 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000559 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000560 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000561 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000562 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
563 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000564 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000565 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000566}
567
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000568int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000569 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000570
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000571 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000572 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000573
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000574 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000575 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000576 }
577 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000578 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000579 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000580}
581
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000582int32_t RTCPSender::BuildSR(const FeedbackState& feedback_state,
583 uint8_t* rtcpbuffer,
584 int& pos,
585 uint32_t NTPsec,
586 uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000587{
588 // sanity
589 if(pos + 52 >= IP_PACKET_SIZE)
590 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000591 LOG(LS_WARNING) << "Failed to build Sender Report.";
niklase@google.com470e71d2011-07-07 08:21:25 +0000592 return -2;
593 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000594 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000595
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000596 uint32_t posNumberOfReportBlocks = pos;
597 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000598
599 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000600 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000601
602 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
603 {
604 // shift old
605 _lastSendReport[i+1] = _lastSendReport[i];
606 _lastRTCPTime[i+1] =_lastRTCPTime[i];
607 }
608
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000609 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000610 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000611
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000612 // The timestamp of this RTCP packet should be estimated as the timestamp of
613 // the frame being captured at this moment. We are calculating that
614 // timestamp as the last frame's timestamp + the time since the last frame
615 // was captured.
pbos@webrtc.org180e5162014-07-11 15:36:26 +0000616 RTPtime = start_timestamp_ + last_rtp_timestamp_ +
617 (_clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
618 (feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000619
620 // Add sender data
621 // Save for our length field
622 pos++;
623 pos++;
624
625 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000626 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000627 pos += 4;
628 // NTP
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000629 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000630 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000631 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000632 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000633 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, RTPtime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000634 pos += 4;
635
636 //sender's packet count
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000637 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000638 feedback_state.packets_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000639 pos += 4;
640
641 //sender's octet count
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000642 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000643 feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000644 pos += 4;
645
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000646 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000647 int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
648 numberOfReportBlocks,
649 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000650 if(retVal < 0)
651 {
652 //
653 return retVal ;
654 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000655 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000656 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
657
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000658 uint16_t len = uint16_t((pos/4) -1);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000659 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000660 return 0;
661}
662
663
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000664int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000665 size_t lengthCname = strlen(_CNAME);
666 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000667
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000668 // sanity
669 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000670 LOG(LS_WARNING) << "Failed to build SDEC.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000671 return -2;
672 }
673 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000674
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000675 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000676 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
677 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000678
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000679 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000680 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000681 pos++;
682 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000683
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000684 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000685 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000686 pos += 4;
687
688 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000689 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000690
691 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000692 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000693
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000694 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000695
696 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
697 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000698 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000699
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000700 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000701 // We must have a zero field even if we have an even multiple of 4 bytes
702 if ((pos % 4) == 0) {
703 padding++;
704 rtcpbuffer[pos++]=0;
705 }
706 while ((pos % 4) != 0) {
707 padding++;
708 rtcpbuffer[pos++]=0;
709 }
710 SDESLength += padding;
711
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000712 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000713 _csrcCNAMEs.begin();
714
715 for(; it != _csrcCNAMEs.end(); it++) {
716 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000717 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000718
719 // Add SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000720 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000721 pos += 4;
722
723 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000724 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000725
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000726 size_t length = strlen(cname->name);
727 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000728
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000729 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000730 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000731
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000732 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000733
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000734 pos += length;
735 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000736 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000737
738 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000739 if((pos % 4) == 0){
740 padding++;
741 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000742 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000743 while((pos % 4) != 0){
744 padding++;
745 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000746 }
747 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000748 }
749 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000750 uint16_t buffer_length = (SDESLength / 4) - 1;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000751 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos, buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000752 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000753}
754
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000755int32_t
756RTCPSender::BuildRR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000757 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000758 const uint32_t NTPsec,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000759 const uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000760{
761 // sanity one block
762 if(pos + 32 >= IP_PACKET_SIZE)
763 {
764 return -2;
765 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000766 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000767
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000768 rtcpbuffer[pos++]=(uint8_t)0x80;
769 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000770
771 // Save for our length field
772 pos++;
773 pos++;
774
775 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000776 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000777 pos += 4;
778
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000779 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000780 int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
781 numberOfReportBlocks,
782 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000783 if(retVal < 0)
784 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000785 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000786 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000787 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000788 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
789
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000790 uint16_t len = uint16_t((pos)/4 -1);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000791 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000792 return 0;
793}
794
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000795// From RFC 5450: Transmission Time Offsets in RTP Streams.
796// 0 1 2 3
797// 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
798// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
799// hdr |V=2|P| RC | PT=IJ=195 | length |
800// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
801// | inter-arrival jitter |
802// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
803// . .
804// . .
805// . .
806// | inter-arrival jitter |
807// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
808//
809// If present, this RTCP packet must be placed after a receiver report
810// (inside a compound RTCP packet), and MUST have the same value for RC
811// (reception report count) as the receiver report.
812
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000813int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000814RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000815 uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000816 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000817 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000818{
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000819 if (external_report_blocks_.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000820 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000821 // TODO(andresp): Remove external report blocks since they are not
822 // supported.
823 LOG(LS_ERROR) << "Handling of external report blocks not implemented.";
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000824 return 0;
825 }
826
827 // sanity
828 if(pos + 8 >= IP_PACKET_SIZE)
829 {
830 return -2;
831 }
832 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000833 uint8_t RC = 1;
834 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
835 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000836
837 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000838 rtcpbuffer[pos++]=(uint8_t)0;
839 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000840
841 // Add inter-arrival jitter
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000842 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
843 jitterTransmissionTimeOffset);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000844 pos += 4;
845 return 0;
846}
847
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000848int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000849RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000850{
851 // sanity
852 if(pos + 12 >= IP_PACKET_SIZE)
853 {
854 return -2;
855 }
856 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000857 uint8_t FMT = 1;
858 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
859 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000860
861 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000862 rtcpbuffer[pos++]=(uint8_t)0;
863 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000864
865 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000866 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000867 pos += 4;
868
869 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000870 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000871 pos += 4;
872 return 0;
873}
874
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000875int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000876 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000877 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000878 // sanity
879 if(pos + 20 >= IP_PACKET_SIZE) {
880 return -2;
881 }
882 if (!repeat) {
883 _sequenceNumberFIR++; // do not increase if repetition
884 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000885
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000886 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000887 uint8_t FMT = 4;
888 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
889 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000890
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000891 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000892 rtcpbuffer[pos++] = (uint8_t)0;
893 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000894
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000895 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000896 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000897 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000898
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000899 // RFC 5104 4.3.1.2. Semantics
900 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000901 rtcpbuffer[pos++] = (uint8_t)0;
902 rtcpbuffer[pos++] = (uint8_t)0;
903 rtcpbuffer[pos++] = (uint8_t)0;
904 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000905
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000906 // Additional Feedback Control Information (FCI)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000907 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000908 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000909
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000910 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
911 rtcpbuffer[pos++] = (uint8_t)0;
912 rtcpbuffer[pos++] = (uint8_t)0;
913 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000914 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000915}
916
917/*
918 0 1 2 3
919 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
920 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
921 | First | Number | PictureID |
922 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
923*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000924int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000925RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000926{
927 // sanity
928 if(pos + 16 >= IP_PACKET_SIZE)
929 {
930 return -2;
931 }
932 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000933 uint8_t FMT = 2;
934 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
935 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000936
937 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000938 rtcpbuffer[pos++]=(uint8_t)0;
939 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000940
941 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000942 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000943 pos += 4;
944
945 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000946 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000947 pos += 4;
948
949 // Add first, number & picture ID 6 bits
950 // first = 0, 13 - bits
951 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000952 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000953 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, sliField);
niklase@google.com470e71d2011-07-07 08:21:25 +0000954 pos += 4;
955 return 0;
956}
957
958/*
959 0 1 2 3
960 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
961 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
962 | PB |0| Payload Type| Native RPSI bit string |
963 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
964 | defined per codec ... | Padding (0) |
965 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
966*/
967/*
968* Note: not generic made for VP8
969*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000970int32_t
971RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000972 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000973 const uint64_t pictureID,
974 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +0000975{
976 // sanity
977 if(pos + 24 >= IP_PACKET_SIZE)
978 {
979 return -2;
980 }
981 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000982 uint8_t FMT = 3;
983 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
984 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000985
986 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000987 uint32_t bitsRequired = 7;
988 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000989 while((pictureID>>bitsRequired) > 0)
990 {
991 bitsRequired += 7;
992 bytesRequired++;
993 }
994
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000995 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +0000996 if(bytesRequired > 6)
997 {
998 size = 5;
999 } else if(bytesRequired > 2)
1000 {
1001 size = 4;
1002 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001003 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001004 rtcpbuffer[pos++]=size;
1005
1006 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001007 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001008 pos += 4;
1009
1010 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001011 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001012 pos += 4;
1013
1014 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001015 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001016 if(paddingBytes == 4)
1017 {
1018 paddingBytes = 0;
1019 }
1020 // add padding length in bits
1021 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1022 pos++;
1023
1024 // add payload type
1025 rtcpbuffer[pos] = payloadType;
1026 pos++;
1027
1028 // add picture ID
1029 for(int i = bytesRequired-1; i > 0; i--)
1030 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001031 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001032 pos++;
1033 }
1034 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001035 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001036 pos++;
1037
1038 // add padding
1039 for(int j = 0; j <paddingBytes; j++)
1040 {
1041 rtcpbuffer[pos] = 0;
1042 pos++;
1043 }
1044 return 0;
1045}
1046
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001047int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001048RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001049{
1050 // sanity
1051 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1052 {
1053 return -2;
1054 }
1055 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001056 uint8_t FMT = 15;
1057 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1058 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001059
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001060 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001061 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1062
1063 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001064 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001065 pos += 4;
1066
1067 // Remote SSRC must be 0
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001068 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, 0);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001069 pos += 4;
1070
1071 rtcpbuffer[pos++]='R';
1072 rtcpbuffer[pos++]='E';
1073 rtcpbuffer[pos++]='M';
1074 rtcpbuffer[pos++]='B';
1075
1076 rtcpbuffer[pos++] = _lengthRembSSRC;
1077 // 6 bit Exp
1078 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001079 uint8_t brExp = 0;
1080 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001081 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001082 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001083 {
1084 brExp = i;
1085 break;
1086 }
1087 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001088 const uint32_t brMantissa = (_rembBitrate >> brExp);
1089 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1090 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1091 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001092
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +00001093 for (int i = 0; i < _lengthRembSSRC; i++)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001094 {
1095 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _rembSSRC[i]);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001096 pos += 4;
1097 }
1098 return 0;
1099}
1100
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001101void
1102RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001103{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001104 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001105 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001106}
1107
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001108int32_t RTCPSender::BuildTMMBR(ModuleRtpRtcpImpl* rtp_rtcp_module,
1109 uint8_t* rtcpbuffer,
1110 int& pos) {
1111 if (rtp_rtcp_module == NULL)
1112 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001113 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1114 // If the sender is an owner of the TMMBN -> send TMMBR
1115 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1116
niklase@google.com470e71d2011-07-07 08:21:25 +00001117 // get current bounding set from RTCP receiver
1118 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001119 // store in candidateSet, allocates one extra slot
1120 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001121
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001122 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1123 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1124 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001125 int32_t lengthOfBoundingSet =
1126 rtp_rtcp_module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001127
1128 if(lengthOfBoundingSet > 0)
1129 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001130 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001131 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001132 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1133 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001134 {
1135 // do not send the same tuple
1136 return 0;
1137 }
1138 }
1139 if(!tmmbrOwner)
1140 {
1141 // use received bounding set as candidate set
1142 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001143 candidateSet->SetEntry(lengthOfBoundingSet,
1144 _tmmbr_Send,
1145 _packetOH_Send,
1146 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001147 int numCandidates = lengthOfBoundingSet+ 1;
1148
1149 // find bounding set
1150 TMMBRSet* boundingSet = NULL;
1151 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1152 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1153 {
1154 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1155 }
1156 if(!tmmbrOwner)
1157 {
1158 // did not enter bounding set, no meaning to send this request
1159 return 0;
1160 }
1161 }
1162 }
1163
1164 if(_tmmbr_Send)
1165 {
1166 // sanity
1167 if(pos + 20 >= IP_PACKET_SIZE)
1168 {
1169 return -2;
1170 }
1171 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001172 uint8_t FMT = 3;
1173 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1174 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001175
1176 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001177 rtcpbuffer[pos++]=(uint8_t)0;
1178 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001179
1180 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001181 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001182 pos += 4;
1183
1184 // RFC 5104 4.2.1.2. Semantics
1185
1186 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001187 rtcpbuffer[pos++]=(uint8_t)0;
1188 rtcpbuffer[pos++]=(uint8_t)0;
1189 rtcpbuffer[pos++]=(uint8_t)0;
1190 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001191
1192 // Additional Feedback Control Information (FCI)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001193 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001194 pos += 4;
1195
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001196 uint32_t bitRate = _tmmbr_Send*1000;
1197 uint32_t mmbrExp = 0;
1198 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001199 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001200 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001201 {
1202 mmbrExp = i;
1203 break;
1204 }
1205 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001206 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001207
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001208 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1209 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1210 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1211 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001212 }
1213 return 0;
1214}
1215
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001216int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001217RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001218{
1219 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1220 if(boundingSet == NULL)
1221 {
1222 return -1;
1223 }
1224 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001225 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001226 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001227 LOG(LS_WARNING) << "Failed to build TMMBN.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001228 return -2;
1229 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001230 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001231 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001232 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1233 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001234
1235 //Add length later
1236 int posLength = pos;
1237 pos++;
1238 pos++;
1239
1240 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001241 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001242 pos += 4;
1243
1244 // RFC 5104 4.2.2.2. Semantics
1245
1246 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001247 rtcpbuffer[pos++]=(uint8_t)0;
1248 rtcpbuffer[pos++]=(uint8_t)0;
1249 rtcpbuffer[pos++]=(uint8_t)0;
1250 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001251
1252 // Additional Feedback Control Information (FCI)
1253 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001254 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001255 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001256 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001257 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001258 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001259 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, tmmbrSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001260 pos += 4;
1261
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001262 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1263 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001264 for(int i=0; i<64; i++)
1265 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001266 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001267 {
1268 mmbrExp = i;
1269 break;
1270 }
1271 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001272 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1273 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001274
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001275 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1276 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1277 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1278 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001279 numBoundingSet++;
1280 }
1281 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001282 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1283 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1284 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001285 return 0;
1286}
1287
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001288int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001289RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001290{
1291 // sanity
1292 if(_appData == NULL)
1293 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001294 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001295 return -1;
1296 }
1297 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1298 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001299 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001300 return -2;
1301 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001302 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001303
1304 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001305 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001306
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001307 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1308 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1309 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001310
1311 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001312 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001313 pos += 4;
1314
1315 // Add our application name
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001316 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _appName);
niklase@google.com470e71d2011-07-07 08:21:25 +00001317 pos += 4;
1318
1319 // Add the data
1320 memcpy(rtcpbuffer +pos, _appData,_appLength);
1321 pos += _appLength;
1322 return 0;
1323}
1324
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001325int32_t
1326RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001327 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001328 const int32_t nackSize,
1329 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001330 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001331{
1332 // sanity
1333 if(pos + 16 >= IP_PACKET_SIZE)
1334 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001335 LOG(LS_WARNING) << "Failed to build NACK.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001336 return -2;
1337 }
1338
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001339 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001340 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001341 uint8_t FMT = 1;
1342 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1343 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001344
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001345 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001346 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001347 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001348
1349 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001350 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001351 pos += 4;
1352
1353 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001354 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001355 pos += 4;
1356
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001357 // Build NACK bitmasks and write them to the RTCP message.
1358 // The nack list should be sorted and not contain duplicates if one
1359 // wants to build the smallest rtcp nack packet.
1360 int numOfNackFields = 0;
1361 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1362 (IP_PACKET_SIZE - pos) / 4);
1363 int i = 0;
1364 while (i < nackSize && numOfNackFields < maxNackFields) {
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001365 uint16_t nack = nackList[i++];
1366 uint16_t bitmask = 0;
1367 while (i < nackSize) {
1368 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1369 if (shift >= 0 && shift <= 15) {
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001370 bitmask |= (1 << shift);
1371 ++i;
1372 } else {
1373 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001374 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001375 }
1376 // Write the sequence number and the bitmask to the packet.
1377 assert(pos + 4 < IP_PACKET_SIZE);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001378 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001379 pos += 2;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001380 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001381 pos += 2;
1382 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001383 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001384 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001385
1386 if (i != nackSize) {
1387 LOG(LS_WARNING) << "Nack list too large for one packet.";
1388 }
1389
1390 // Report stats.
1391 NACKStringBuilder stringBuilder;
1392 for (int idx = 0; idx < i; ++idx) {
1393 stringBuilder.PushNACK(nackList[idx]);
1394 nack_stats_.ReportRequest(nackList[idx]);
1395 }
edjee@google.com79b02892013-04-04 19:43:34 +00001396 *nackString = stringBuilder.GetResult();
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001397 packet_type_counter_.nack_requests = nack_stats_.requests();
1398 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
niklase@google.com470e71d2011-07-07 08:21:25 +00001399 return 0;
1400}
1401
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001402int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001403RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001404{
1405 // sanity
1406 if(pos + 8 >= IP_PACKET_SIZE)
1407 {
1408 return -2;
1409 }
1410 if(_includeCSRCs)
1411 {
1412 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001413 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1414 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001415
1416 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001417 rtcpbuffer[pos++]=(uint8_t)0;
1418 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001419
1420 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001421 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001422 pos += 4;
1423
1424 // add CSRCs
1425 for(int i = 0; i < _CSRCs; i++)
1426 {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001427 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _CSRC[i]);
niklase@google.com470e71d2011-07-07 08:21:25 +00001428 pos += 4;
1429 }
1430 } else
1431 {
1432 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001433 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1434 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001435
1436 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001437 rtcpbuffer[pos++]=(uint8_t)0;
1438 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001439
1440 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001441 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001442 pos += 4;
1443 }
1444 return 0;
1445}
1446
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001447int32_t RTCPSender::BuildReceiverReferenceTime(uint8_t* buffer,
1448 int& pos,
1449 uint32_t ntp_sec,
1450 uint32_t ntp_frac) {
1451 const int kRrTimeBlockLength = 20;
1452 if (pos + kRrTimeBlockLength >= IP_PACKET_SIZE) {
1453 return -2;
1454 }
1455
1456 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) {
1457 last_xr_rr_.erase(last_xr_rr_.begin());
1458 }
1459 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
1460 RTCPUtility::MidNtp(ntp_sec, ntp_frac),
1461 Clock::NtpToMs(ntp_sec, ntp_frac)));
1462
1463 // Add XR header.
1464 buffer[pos++] = 0x80;
1465 buffer[pos++] = 207;
1466 buffer[pos++] = 0; // XR packet length.
1467 buffer[pos++] = 4; // XR packet length.
1468
1469 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001470 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001471 pos += 4;
1472
1473 // 0 1 2 3
1474 // 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
1475 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1476 // | BT=4 | reserved | block length = 2 |
1477 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1478 // | NTP timestamp, most significant word |
1479 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1480 // | NTP timestamp, least significant word |
1481 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1482
1483 // Add Receiver Reference Time Report block.
1484 buffer[pos++] = 4; // BT.
1485 buffer[pos++] = 0; // Reserved.
1486 buffer[pos++] = 0; // Block length.
1487 buffer[pos++] = 2; // Block length.
1488
1489 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001490 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_sec);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001491 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001492 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001493 pos += 4;
1494
1495 return 0;
1496}
1497
1498int32_t RTCPSender::BuildDlrr(uint8_t* buffer,
1499 int& pos,
1500 const RtcpReceiveTimeInfo& info) {
1501 const int kDlrrBlockLength = 24;
1502 if (pos + kDlrrBlockLength >= IP_PACKET_SIZE) {
1503 return -2;
1504 }
1505
1506 // Add XR header.
1507 buffer[pos++] = 0x80;
1508 buffer[pos++] = 207;
1509 buffer[pos++] = 0; // XR packet length.
1510 buffer[pos++] = 5; // XR packet length.
1511
1512 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001513 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001514 pos += 4;
1515
1516 // 0 1 2 3
1517 // 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
1518 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1519 // | BT=5 | reserved | block length |
1520 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1521 // | SSRC_1 (SSRC of first receiver) | sub-
1522 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1523 // | last RR (LRR) | 1
1524 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1525 // | delay since last RR (DLRR) |
1526 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1527 // | SSRC_2 (SSRC of second receiver) | sub-
1528 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1529 // : ... : 2
1530
1531 // Add DLRR sub block.
1532 buffer[pos++] = 5; // BT.
1533 buffer[pos++] = 0; // Reserved.
1534 buffer[pos++] = 0; // Block length.
1535 buffer[pos++] = 3; // Block length.
1536
1537 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001538 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.sourceSSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001539 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001540 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.lastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001541 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001542 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.delaySinceLastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001543 pos += 4;
1544
1545 return 0;
1546}
1547
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001548int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001549RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001550{
1551 // sanity
1552 if(pos + 44 >= IP_PACKET_SIZE)
1553 {
1554 return -2;
1555 }
1556
1557 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001558 rtcpbuffer[pos++]=(uint8_t)0x80;
1559 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001560
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001561 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001562
1563 // handle length later on
1564 pos++;
1565 pos++;
1566
1567 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001568 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001569 pos += 4;
1570
1571 // Add a VoIP metrics block
1572 rtcpbuffer[pos++]=7;
1573 rtcpbuffer[pos++]=0;
1574 rtcpbuffer[pos++]=0;
1575 rtcpbuffer[pos++]=8;
1576
1577 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001578 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001579 pos += 4;
1580
1581 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1582 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1583 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1584 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1585
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001586 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1587 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1588 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1589 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001590
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001591 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1592 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1593 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1594 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001595
1596 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1597 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1598 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1599 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1600
1601 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1602 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1603 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1604 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1605
1606 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1607 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001608 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1609 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001610
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001611 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1612 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1613 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1614 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001615
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001616 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1617 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001618 return 0;
1619}
1620
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001621int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
1622 uint32_t packetTypeFlags,
1623 int32_t nackSize,
1624 const uint16_t* nackList,
1625 bool repeat,
1626 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001627 {
1628 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1629 if(_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001630 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001631 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001632 return -1;
1633 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001634 }
1635 uint8_t rtcp_buffer[IP_PACKET_SIZE];
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001636 int rtcp_length = PrepareRTCP(feedback_state,
1637 packetTypeFlags,
1638 nackSize,
1639 nackList,
1640 repeat,
1641 pictureID,
1642 rtcp_buffer,
1643 IP_PACKET_SIZE);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001644 if (rtcp_length < 0) {
1645 return -1;
1646 }
1647 // Sanity don't send empty packets.
1648 if (rtcp_length == 0)
1649 {
1650 return -1;
1651 }
1652 return SendToNetwork(rtcp_buffer, static_cast<uint16_t>(rtcp_length));
1653}
1654
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001655int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
1656 uint32_t packetTypeFlags,
1657 int32_t nackSize,
1658 const uint16_t* nackList,
1659 bool repeat,
1660 uint64_t pictureID,
1661 uint8_t* rtcp_buffer,
1662 int buffer_size) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001663 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1664 // Collect the received information.
1665 uint32_t NTPsec = 0;
1666 uint32_t NTPfrac = 0;
1667 uint32_t jitterTransmissionOffset = 0;
1668 int position = 0;
1669
1670 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1671
1672 if(_TMMBR ) // Attach TMMBR to send and receive reports.
1673 {
1674 rtcpPacketTypeFlags |= kRtcpTmmbr;
1675 }
1676 if(_appSend)
1677 {
1678 rtcpPacketTypeFlags |= kRtcpApp;
1679 _appSend = false;
1680 }
1681 if(_REMB && _sendREMB)
1682 {
1683 // Always attach REMB to SR if that is configured. Note that REMB is
1684 // only sent on one of the RTP modules in the REMB group.
1685 rtcpPacketTypeFlags |= kRtcpRemb;
1686 }
1687 if(_xrSendVoIPMetric)
1688 {
1689 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1690 _xrSendVoIPMetric = false;
1691 }
1692 if(_sendTMMBN) // Set when having received a TMMBR.
1693 {
1694 rtcpPacketTypeFlags |= kRtcpTmmbn;
1695 _sendTMMBN = false;
1696 }
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001697 if (rtcpPacketTypeFlags & kRtcpReport)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001698 {
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001699 if (xrSendReceiverReferenceTimeEnabled_ && !_sending)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001700 {
1701 rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
1702 }
1703 if (feedback_state.has_last_xr_rr)
1704 {
1705 rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
1706 }
1707 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001708 if(_method == kRtcpCompound)
1709 {
1710 if(_sending)
1711 {
1712 rtcpPacketTypeFlags |= kRtcpSr;
1713 } else
1714 {
1715 rtcpPacketTypeFlags |= kRtcpRr;
1716 }
1717 } else if(_method == kRtcpNonCompound)
1718 {
1719 if(rtcpPacketTypeFlags & kRtcpReport)
1720 {
1721 if(_sending)
1722 {
1723 rtcpPacketTypeFlags |= kRtcpSr;
1724 } else
1725 {
1726 rtcpPacketTypeFlags |= kRtcpRr;
1727 }
1728 }
1729 }
1730 if( rtcpPacketTypeFlags & kRtcpRr ||
1731 rtcpPacketTypeFlags & kRtcpSr)
1732 {
1733 // generate next time to send a RTCP report
1734 // seeded from RTP constructor
1735 int32_t random = rand() % 1000;
1736 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1737
1738 if(_audio)
1739 {
1740 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1741 (RTCP_INTERVAL_AUDIO_MS*random/1000);
1742 }else
1743 {
1744 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1745 if(_sending)
1746 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001747 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1748 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1749 if (send_bitrate_kbit != 0)
1750 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001751 }
1752 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1753 {
1754 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1755 }
1756 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1757 }
1758 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1759 }
1760
1761 // If the data does not fit in the packet we fill it as much as possible.
1762 int32_t buildVal = 0;
1763
1764 // We need to send our NTP even if we haven't received any reports.
1765 _clock->CurrentNtp(NTPsec, NTPfrac);
1766 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1767 StatisticianMap statisticians =
1768 receive_statistics_->GetActiveStatisticians();
1769 if (!statisticians.empty()) {
1770 StatisticianMap::const_iterator it;
1771 int i;
1772 for (it = statisticians.begin(), i = 0; it != statisticians.end();
1773 ++it, ++i) {
1774 RTCPReportBlock report_block;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001775 if (PrepareReport(
1776 feedback_state, it->second, &report_block, &NTPsec, &NTPfrac))
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001777 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1778 }
1779 if (_IJ && !statisticians.empty()) {
1780 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1781 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001782 }
1783 }
1784
1785 if(rtcpPacketTypeFlags & kRtcpSr)
1786 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001787 buildVal = BuildSR(feedback_state, rtcp_buffer, position, NTPsec, NTPfrac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001788 if (buildVal == -1) {
1789 return -1;
1790 } else if (buildVal == -2) {
1791 return position;
1792 }
1793 buildVal = BuildSDEC(rtcp_buffer, position);
1794 if (buildVal == -1) {
1795 return -1;
1796 } else if (buildVal == -2) {
1797 return position;
1798 }
1799 }else if(rtcpPacketTypeFlags & kRtcpRr)
1800 {
1801 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1802 if (buildVal == -1) {
1803 return -1;
1804 } else if (buildVal == -2) {
1805 return position;
1806 }
1807 // only of set
1808 if(_CNAME[0] != 0)
1809 {
1810 buildVal = BuildSDEC(rtcp_buffer, position);
1811 if (buildVal == -1) {
1812 return -1;
1813 }
1814 }
1815 }
1816 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1817 {
1818 // If present, this RTCP packet must be placed after a
1819 // receiver report.
1820 buildVal = BuildExtendedJitterReport(rtcp_buffer,
1821 position,
1822 jitterTransmissionOffset);
1823 if (buildVal == -1) {
1824 return -1;
1825 } else if (buildVal == -2) {
1826 return position;
1827 }
1828 }
1829 if(rtcpPacketTypeFlags & kRtcpPli)
1830 {
1831 buildVal = BuildPLI(rtcp_buffer, position);
1832 if (buildVal == -1) {
1833 return -1;
1834 } else if (buildVal == -2) {
1835 return position;
1836 }
1837 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001838 ++packet_type_counter_.pli_packets;
1839 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC,
1840 packet_type_counter_.pli_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001841 }
1842 if(rtcpPacketTypeFlags & kRtcpFir)
1843 {
1844 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1845 if (buildVal == -1) {
1846 return -1;
1847 } else if (buildVal == -2) {
1848 return position;
1849 }
1850 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001851 ++packet_type_counter_.fir_packets;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001852 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001853 packet_type_counter_.fir_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001854 }
1855 if(rtcpPacketTypeFlags & kRtcpSli)
1856 {
1857 buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1858 if (buildVal == -1) {
1859 return -1;
1860 } else if (buildVal == -2) {
1861 return position;
1862 }
1863 }
1864 if(rtcpPacketTypeFlags & kRtcpRpsi)
1865 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001866 const int8_t payloadType = feedback_state.send_payload_type;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001867 if (payloadType == -1) {
1868 return -1;
1869 }
1870 buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1871 (uint8_t)payloadType);
1872 if (buildVal == -1) {
1873 return -1;
1874 } else if (buildVal == -2) {
1875 return position;
1876 }
1877 }
1878 if(rtcpPacketTypeFlags & kRtcpRemb)
1879 {
1880 buildVal = BuildREMB(rtcp_buffer, position);
1881 if (buildVal == -1) {
1882 return -1;
1883 } else if (buildVal == -2) {
1884 return position;
1885 }
1886 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1887 }
1888 if(rtcpPacketTypeFlags & kRtcpBye)
1889 {
1890 buildVal = BuildBYE(rtcp_buffer, position);
1891 if (buildVal == -1) {
1892 return -1;
1893 } else if (buildVal == -2) {
1894 return position;
1895 }
1896 }
1897 if(rtcpPacketTypeFlags & kRtcpApp)
1898 {
1899 buildVal = BuildAPP(rtcp_buffer, position);
1900 if (buildVal == -1) {
1901 return -1;
1902 } else if (buildVal == -2) {
1903 return position;
1904 }
1905 }
1906 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1907 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001908 buildVal = BuildTMMBR(feedback_state.module, rtcp_buffer, position);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001909 if (buildVal == -1) {
1910 return -1;
1911 } else if (buildVal == -2) {
1912 return position;
1913 }
1914 }
1915 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1916 {
1917 buildVal = BuildTMMBN(rtcp_buffer, position);
1918 if (buildVal == -1) {
1919 return -1;
1920 } else if (buildVal == -2) {
1921 return position;
1922 }
1923 }
1924 if(rtcpPacketTypeFlags & kRtcpNack)
1925 {
1926 std::string nackString;
1927 buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
1928 &nackString);
1929 if (buildVal == -1) {
1930 return -1;
1931 } else if (buildVal == -2) {
1932 return position;
1933 }
1934 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
1935 "nacks", TRACE_STR_COPY(nackString.c_str()));
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001936 ++packet_type_counter_.nack_packets;
1937 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC,
1938 packet_type_counter_.nack_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001939 }
1940 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1941 {
1942 buildVal = BuildVoIPMetric(rtcp_buffer, position);
1943 if (buildVal == -1) {
1944 return -1;
1945 } else if (buildVal == -2) {
1946 return position;
1947 }
1948 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001949 if (rtcpPacketTypeFlags & kRtcpXrReceiverReferenceTime)
1950 {
1951 buildVal = BuildReceiverReferenceTime(rtcp_buffer,
1952 position,
1953 NTPsec,
1954 NTPfrac);
1955 if (buildVal == -1) {
1956 return -1;
1957 } else if (buildVal == -2) {
1958 return position;
1959 }
1960 }
1961 if (rtcpPacketTypeFlags & kRtcpXrDlrrReportBlock)
1962 {
1963 buildVal = BuildDlrr(rtcp_buffer, position, feedback_state.last_xr_rr);
1964 if (buildVal == -1) {
1965 return -1;
1966 } else if (buildVal == -2) {
1967 return position;
1968 }
1969 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001970 return position;
1971}
1972
1973bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
1974 return Status() == kRtcpCompound ||
1975 (rtcp_packet_type & kRtcpReport) ||
1976 (rtcp_packet_type & kRtcpSr) ||
1977 (rtcp_packet_type & kRtcpRr);
1978}
1979
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001980bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
1981 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001982 RTCPReportBlock* report_block,
1983 uint32_t* ntp_secs, uint32_t* ntp_frac) {
1984 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001985 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001986 if (!statistician->GetStatistics(&stats, true))
1987 return false;
1988 report_block->fractionLost = stats.fraction_lost;
1989 report_block->cumulativeLost = stats.cumulative_lost;
1990 report_block->extendedHighSeqNum =
1991 stats.extended_max_sequence_number;
1992 report_block->jitter = stats.jitter;
1993
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001994 // get our NTP as late as possible to avoid a race
1995 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
1996
1997 // Delay since last received report
1998 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001999 if ((feedback_state.last_rr_ntp_secs != 0) ||
2000 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002001 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
2002 uint32_t now=*ntp_secs&0x0000FFFF;
2003 now <<=16;
2004 now += (*ntp_frac&0xffff0000)>>16;
2005
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002006 uint32_t receiveTime = feedback_state.last_rr_ntp_secs&0x0000FFFF;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002007 receiveTime <<=16;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002008 receiveTime += (feedback_state.last_rr_ntp_frac&0xffff0000)>>16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002009
2010 delaySinceLastReceivedSR = now-receiveTime;
2011 }
2012 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002013 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002014 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00002015}
2016
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002017int32_t
2018RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
2019 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002020{
2021 CriticalSectionScoped lock(_criticalSectionTransport);
2022 if(_cbTransport)
2023 {
2024 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
2025 {
2026 return 0;
2027 }
2028 }
2029 return -1;
2030}
2031
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002032int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002033RTCPSender::SetCSRCStatus(const bool include)
2034{
pbos@webrtc.org180e5162014-07-11 15:36:26 +00002035 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +00002036 _includeCSRCs = include;
2037 return 0;
2038}
2039
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002040int32_t
2041RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
2042 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00002043{
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002044 assert(arrLength <= kRtpCsrcSize);
niklase@google.com470e71d2011-07-07 08:21:25 +00002045 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2046
2047 for(int i = 0; i < arrLength;i++)
2048 {
2049 _CSRC[i] = arrOfCSRC[i];
2050 }
2051 _CSRCs = arrLength;
2052 return 0;
2053}
2054
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002055int32_t
2056RTCPSender::SetApplicationSpecificData(const uint8_t subType,
2057 const uint32_t name,
2058 const uint8_t* data,
2059 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002060{
2061 if(length %4 != 0)
2062 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002063 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
niklase@google.com470e71d2011-07-07 08:21:25 +00002064 return -1;
2065 }
2066 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2067
2068 if(_appData)
2069 {
2070 delete [] _appData;
2071 }
2072
2073 _appSend = true;
2074 _appSubType = subType;
2075 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002076 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002077 _appLength = length;
2078 memcpy(_appData, data, length);
2079 return 0;
2080}
2081
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002082int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002083RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2084{
2085 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2086 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2087
2088 _xrSendVoIPMetric = true;
2089 return 0;
2090}
2091
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002092void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
2093 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2094 xrSendReceiverReferenceTimeEnabled_ = enable;
2095}
2096
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00002097bool RTCPSender::RtcpXrReceiverReferenceTime() const {
2098 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2099 return xrSendReceiverReferenceTimeEnabled_;
2100}
2101
niklase@google.com470e71d2011-07-07 08:21:25 +00002102// called under critsect _criticalSectionRTCPSender
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002103int32_t RTCPSender::WriteAllReportBlocksToBuffer(
2104 uint8_t* rtcpbuffer,
2105 int pos,
2106 uint8_t& numberOfReportBlocks,
2107 const uint32_t NTPsec,
2108 const uint32_t NTPfrac) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002109 numberOfReportBlocks = external_report_blocks_.size();
2110 numberOfReportBlocks += internal_report_blocks_.size();
2111 if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002112 LOG(LS_WARNING) << "Can't fit all report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002113 return -1;
2114 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002115 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2116 while (!internal_report_blocks_.empty()) {
2117 delete internal_report_blocks_.begin()->second;
2118 internal_report_blocks_.erase(internal_report_blocks_.begin());
2119 }
2120 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2121 return pos;
2122}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002123
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002124int32_t RTCPSender::WriteReportBlocksToBuffer(
2125 uint8_t* rtcpbuffer,
2126 int32_t position,
2127 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2128 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2129 report_blocks.begin();
2130 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002131 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002132 RTCPReportBlock* reportBlock = it->second;
2133 if (reportBlock) {
2134 // Remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002135 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position, remoteSSRC);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002136 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002137
2138 // fraction lost
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002139 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002140
2141 // cumulative loss
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002142 RtpUtility::AssignUWord24ToBuffer(rtcpbuffer + position,
2143 reportBlock->cumulativeLost);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002144 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002145
2146 // extended highest seq_no, contain the highest sequence number received
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002147 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2148 reportBlock->extendedHighSeqNum);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002149 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002150
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002151 // Jitter
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002152 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2153 reportBlock->jitter);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002154 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002155
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002156 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2157 reportBlock->lastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002158 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002159
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002160 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2161 reportBlock->delaySinceLastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002162 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002163 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002164 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002165 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00002166}
2167
2168// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002169int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002170RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002171 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002172{
2173 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2174
2175 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2176 {
2177 _sendTMMBN = true;
2178 return 0;
2179 }
2180 return -1;
2181}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002182} // namespace webrtc