blob: 1edbee43349b848abaf5895f0d760e9061f2be53 [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
edjee@google.com79b02892013-04-04 19:43:34 +00001357 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001358 // Build NACK bitmasks and write them to the RTCP message.
1359 // The nack list should be sorted and not contain duplicates if one
1360 // wants to build the smallest rtcp nack packet.
1361 int numOfNackFields = 0;
1362 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1363 (IP_PACKET_SIZE - pos) / 4);
1364 int i = 0;
1365 while (i < nackSize && numOfNackFields < maxNackFields) {
1366 stringBuilder.PushNACK(nackList[i]);
1367 uint16_t nack = nackList[i++];
1368 uint16_t bitmask = 0;
1369 while (i < nackSize) {
1370 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1371 if (shift >= 0 && shift <= 15) {
1372 stringBuilder.PushNACK(nackList[i]);
1373 bitmask |= (1 << shift);
1374 ++i;
1375 } else {
1376 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001377 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001378 }
1379 // Write the sequence number and the bitmask to the packet.
1380 assert(pos + 4 < IP_PACKET_SIZE);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001381 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001382 pos += 2;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001383 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001384 pos += 2;
1385 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001386 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001387 if (i != nackSize) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001388 LOG(LS_WARNING) << "Nack list to large for one packet.";
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001389 }
1390 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001391 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001392 return 0;
1393}
1394
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001395int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001396RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001397{
1398 // sanity
1399 if(pos + 8 >= IP_PACKET_SIZE)
1400 {
1401 return -2;
1402 }
1403 if(_includeCSRCs)
1404 {
1405 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001406 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1407 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001408
1409 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001410 rtcpbuffer[pos++]=(uint8_t)0;
1411 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001412
1413 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001414 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001415 pos += 4;
1416
1417 // add CSRCs
1418 for(int i = 0; i < _CSRCs; i++)
1419 {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001420 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _CSRC[i]);
niklase@google.com470e71d2011-07-07 08:21:25 +00001421 pos += 4;
1422 }
1423 } else
1424 {
1425 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001426 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1427 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001428
1429 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001430 rtcpbuffer[pos++]=(uint8_t)0;
1431 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001432
1433 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001434 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001435 pos += 4;
1436 }
1437 return 0;
1438}
1439
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001440int32_t RTCPSender::BuildReceiverReferenceTime(uint8_t* buffer,
1441 int& pos,
1442 uint32_t ntp_sec,
1443 uint32_t ntp_frac) {
1444 const int kRrTimeBlockLength = 20;
1445 if (pos + kRrTimeBlockLength >= IP_PACKET_SIZE) {
1446 return -2;
1447 }
1448
1449 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) {
1450 last_xr_rr_.erase(last_xr_rr_.begin());
1451 }
1452 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
1453 RTCPUtility::MidNtp(ntp_sec, ntp_frac),
1454 Clock::NtpToMs(ntp_sec, ntp_frac)));
1455
1456 // Add XR header.
1457 buffer[pos++] = 0x80;
1458 buffer[pos++] = 207;
1459 buffer[pos++] = 0; // XR packet length.
1460 buffer[pos++] = 4; // XR packet length.
1461
1462 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001463 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001464 pos += 4;
1465
1466 // 0 1 2 3
1467 // 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
1468 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1469 // | BT=4 | reserved | block length = 2 |
1470 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1471 // | NTP timestamp, most significant word |
1472 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1473 // | NTP timestamp, least significant word |
1474 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1475
1476 // Add Receiver Reference Time Report block.
1477 buffer[pos++] = 4; // BT.
1478 buffer[pos++] = 0; // Reserved.
1479 buffer[pos++] = 0; // Block length.
1480 buffer[pos++] = 2; // Block length.
1481
1482 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001483 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_sec);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001484 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001485 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001486 pos += 4;
1487
1488 return 0;
1489}
1490
1491int32_t RTCPSender::BuildDlrr(uint8_t* buffer,
1492 int& pos,
1493 const RtcpReceiveTimeInfo& info) {
1494 const int kDlrrBlockLength = 24;
1495 if (pos + kDlrrBlockLength >= IP_PACKET_SIZE) {
1496 return -2;
1497 }
1498
1499 // Add XR header.
1500 buffer[pos++] = 0x80;
1501 buffer[pos++] = 207;
1502 buffer[pos++] = 0; // XR packet length.
1503 buffer[pos++] = 5; // XR packet length.
1504
1505 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001506 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001507 pos += 4;
1508
1509 // 0 1 2 3
1510 // 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
1511 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1512 // | BT=5 | reserved | block length |
1513 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1514 // | SSRC_1 (SSRC of first receiver) | sub-
1515 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1516 // | last RR (LRR) | 1
1517 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1518 // | delay since last RR (DLRR) |
1519 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1520 // | SSRC_2 (SSRC of second receiver) | sub-
1521 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1522 // : ... : 2
1523
1524 // Add DLRR sub block.
1525 buffer[pos++] = 5; // BT.
1526 buffer[pos++] = 0; // Reserved.
1527 buffer[pos++] = 0; // Block length.
1528 buffer[pos++] = 3; // Block length.
1529
1530 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001531 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.sourceSSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001532 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001533 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.lastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001534 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001535 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.delaySinceLastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001536 pos += 4;
1537
1538 return 0;
1539}
1540
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001541int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001542RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001543{
1544 // sanity
1545 if(pos + 44 >= IP_PACKET_SIZE)
1546 {
1547 return -2;
1548 }
1549
1550 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001551 rtcpbuffer[pos++]=(uint8_t)0x80;
1552 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001553
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001554 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001555
1556 // handle length later on
1557 pos++;
1558 pos++;
1559
1560 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001561 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001562 pos += 4;
1563
1564 // Add a VoIP metrics block
1565 rtcpbuffer[pos++]=7;
1566 rtcpbuffer[pos++]=0;
1567 rtcpbuffer[pos++]=0;
1568 rtcpbuffer[pos++]=8;
1569
1570 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001571 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001572 pos += 4;
1573
1574 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1575 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1576 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1577 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1578
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001579 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1580 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1581 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1582 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001583
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001584 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1585 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1586 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1587 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001588
1589 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1590 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1591 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1592 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1593
1594 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1595 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1596 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1597 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1598
1599 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1600 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001601 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1602 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001603
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001604 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1605 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1606 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1607 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001608
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001609 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1610 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001611 return 0;
1612}
1613
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001614int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
1615 uint32_t packetTypeFlags,
1616 int32_t nackSize,
1617 const uint16_t* nackList,
1618 bool repeat,
1619 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001620 {
1621 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1622 if(_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001623 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001624 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001625 return -1;
1626 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001627 }
1628 uint8_t rtcp_buffer[IP_PACKET_SIZE];
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001629 int rtcp_length = PrepareRTCP(feedback_state,
1630 packetTypeFlags,
1631 nackSize,
1632 nackList,
1633 repeat,
1634 pictureID,
1635 rtcp_buffer,
1636 IP_PACKET_SIZE);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001637 if (rtcp_length < 0) {
1638 return -1;
1639 }
1640 // Sanity don't send empty packets.
1641 if (rtcp_length == 0)
1642 {
1643 return -1;
1644 }
1645 return SendToNetwork(rtcp_buffer, static_cast<uint16_t>(rtcp_length));
1646}
1647
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001648int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
1649 uint32_t packetTypeFlags,
1650 int32_t nackSize,
1651 const uint16_t* nackList,
1652 bool repeat,
1653 uint64_t pictureID,
1654 uint8_t* rtcp_buffer,
1655 int buffer_size) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001656 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1657 // Collect the received information.
1658 uint32_t NTPsec = 0;
1659 uint32_t NTPfrac = 0;
1660 uint32_t jitterTransmissionOffset = 0;
1661 int position = 0;
1662
1663 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1664
1665 if(_TMMBR ) // Attach TMMBR to send and receive reports.
1666 {
1667 rtcpPacketTypeFlags |= kRtcpTmmbr;
1668 }
1669 if(_appSend)
1670 {
1671 rtcpPacketTypeFlags |= kRtcpApp;
1672 _appSend = false;
1673 }
1674 if(_REMB && _sendREMB)
1675 {
1676 // Always attach REMB to SR if that is configured. Note that REMB is
1677 // only sent on one of the RTP modules in the REMB group.
1678 rtcpPacketTypeFlags |= kRtcpRemb;
1679 }
1680 if(_xrSendVoIPMetric)
1681 {
1682 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1683 _xrSendVoIPMetric = false;
1684 }
1685 if(_sendTMMBN) // Set when having received a TMMBR.
1686 {
1687 rtcpPacketTypeFlags |= kRtcpTmmbn;
1688 _sendTMMBN = false;
1689 }
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001690 if (rtcpPacketTypeFlags & kRtcpReport)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001691 {
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001692 if (xrSendReceiverReferenceTimeEnabled_ && !_sending)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001693 {
1694 rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
1695 }
1696 if (feedback_state.has_last_xr_rr)
1697 {
1698 rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
1699 }
1700 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001701 if(_method == kRtcpCompound)
1702 {
1703 if(_sending)
1704 {
1705 rtcpPacketTypeFlags |= kRtcpSr;
1706 } else
1707 {
1708 rtcpPacketTypeFlags |= kRtcpRr;
1709 }
1710 } else if(_method == kRtcpNonCompound)
1711 {
1712 if(rtcpPacketTypeFlags & kRtcpReport)
1713 {
1714 if(_sending)
1715 {
1716 rtcpPacketTypeFlags |= kRtcpSr;
1717 } else
1718 {
1719 rtcpPacketTypeFlags |= kRtcpRr;
1720 }
1721 }
1722 }
1723 if( rtcpPacketTypeFlags & kRtcpRr ||
1724 rtcpPacketTypeFlags & kRtcpSr)
1725 {
1726 // generate next time to send a RTCP report
1727 // seeded from RTP constructor
1728 int32_t random = rand() % 1000;
1729 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1730
1731 if(_audio)
1732 {
1733 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1734 (RTCP_INTERVAL_AUDIO_MS*random/1000);
1735 }else
1736 {
1737 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1738 if(_sending)
1739 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001740 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1741 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1742 if (send_bitrate_kbit != 0)
1743 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001744 }
1745 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1746 {
1747 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1748 }
1749 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1750 }
1751 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1752 }
1753
1754 // If the data does not fit in the packet we fill it as much as possible.
1755 int32_t buildVal = 0;
1756
1757 // We need to send our NTP even if we haven't received any reports.
1758 _clock->CurrentNtp(NTPsec, NTPfrac);
1759 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1760 StatisticianMap statisticians =
1761 receive_statistics_->GetActiveStatisticians();
1762 if (!statisticians.empty()) {
1763 StatisticianMap::const_iterator it;
1764 int i;
1765 for (it = statisticians.begin(), i = 0; it != statisticians.end();
1766 ++it, ++i) {
1767 RTCPReportBlock report_block;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001768 if (PrepareReport(
1769 feedback_state, it->second, &report_block, &NTPsec, &NTPfrac))
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001770 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1771 }
1772 if (_IJ && !statisticians.empty()) {
1773 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1774 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001775 }
1776 }
1777
1778 if(rtcpPacketTypeFlags & kRtcpSr)
1779 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001780 buildVal = BuildSR(feedback_state, rtcp_buffer, position, NTPsec, NTPfrac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001781 if (buildVal == -1) {
1782 return -1;
1783 } else if (buildVal == -2) {
1784 return position;
1785 }
1786 buildVal = BuildSDEC(rtcp_buffer, position);
1787 if (buildVal == -1) {
1788 return -1;
1789 } else if (buildVal == -2) {
1790 return position;
1791 }
1792 }else if(rtcpPacketTypeFlags & kRtcpRr)
1793 {
1794 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1795 if (buildVal == -1) {
1796 return -1;
1797 } else if (buildVal == -2) {
1798 return position;
1799 }
1800 // only of set
1801 if(_CNAME[0] != 0)
1802 {
1803 buildVal = BuildSDEC(rtcp_buffer, position);
1804 if (buildVal == -1) {
1805 return -1;
1806 }
1807 }
1808 }
1809 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1810 {
1811 // If present, this RTCP packet must be placed after a
1812 // receiver report.
1813 buildVal = BuildExtendedJitterReport(rtcp_buffer,
1814 position,
1815 jitterTransmissionOffset);
1816 if (buildVal == -1) {
1817 return -1;
1818 } else if (buildVal == -2) {
1819 return position;
1820 }
1821 }
1822 if(rtcpPacketTypeFlags & kRtcpPli)
1823 {
1824 buildVal = BuildPLI(rtcp_buffer, position);
1825 if (buildVal == -1) {
1826 return -1;
1827 } else if (buildVal == -2) {
1828 return position;
1829 }
1830 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001831 ++packet_type_counter_.pli_packets;
1832 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC,
1833 packet_type_counter_.pli_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001834 }
1835 if(rtcpPacketTypeFlags & kRtcpFir)
1836 {
1837 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1838 if (buildVal == -1) {
1839 return -1;
1840 } else if (buildVal == -2) {
1841 return position;
1842 }
1843 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001844 ++packet_type_counter_.fir_packets;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001845 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001846 packet_type_counter_.fir_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001847 }
1848 if(rtcpPacketTypeFlags & kRtcpSli)
1849 {
1850 buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1851 if (buildVal == -1) {
1852 return -1;
1853 } else if (buildVal == -2) {
1854 return position;
1855 }
1856 }
1857 if(rtcpPacketTypeFlags & kRtcpRpsi)
1858 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001859 const int8_t payloadType = feedback_state.send_payload_type;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001860 if (payloadType == -1) {
1861 return -1;
1862 }
1863 buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1864 (uint8_t)payloadType);
1865 if (buildVal == -1) {
1866 return -1;
1867 } else if (buildVal == -2) {
1868 return position;
1869 }
1870 }
1871 if(rtcpPacketTypeFlags & kRtcpRemb)
1872 {
1873 buildVal = BuildREMB(rtcp_buffer, position);
1874 if (buildVal == -1) {
1875 return -1;
1876 } else if (buildVal == -2) {
1877 return position;
1878 }
1879 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1880 }
1881 if(rtcpPacketTypeFlags & kRtcpBye)
1882 {
1883 buildVal = BuildBYE(rtcp_buffer, position);
1884 if (buildVal == -1) {
1885 return -1;
1886 } else if (buildVal == -2) {
1887 return position;
1888 }
1889 }
1890 if(rtcpPacketTypeFlags & kRtcpApp)
1891 {
1892 buildVal = BuildAPP(rtcp_buffer, position);
1893 if (buildVal == -1) {
1894 return -1;
1895 } else if (buildVal == -2) {
1896 return position;
1897 }
1898 }
1899 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1900 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001901 buildVal = BuildTMMBR(feedback_state.module, rtcp_buffer, position);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001902 if (buildVal == -1) {
1903 return -1;
1904 } else if (buildVal == -2) {
1905 return position;
1906 }
1907 }
1908 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1909 {
1910 buildVal = BuildTMMBN(rtcp_buffer, position);
1911 if (buildVal == -1) {
1912 return -1;
1913 } else if (buildVal == -2) {
1914 return position;
1915 }
1916 }
1917 if(rtcpPacketTypeFlags & kRtcpNack)
1918 {
1919 std::string nackString;
1920 buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
1921 &nackString);
1922 if (buildVal == -1) {
1923 return -1;
1924 } else if (buildVal == -2) {
1925 return position;
1926 }
1927 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
1928 "nacks", TRACE_STR_COPY(nackString.c_str()));
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001929 ++packet_type_counter_.nack_packets;
1930 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC,
1931 packet_type_counter_.nack_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001932 }
1933 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1934 {
1935 buildVal = BuildVoIPMetric(rtcp_buffer, position);
1936 if (buildVal == -1) {
1937 return -1;
1938 } else if (buildVal == -2) {
1939 return position;
1940 }
1941 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001942 if (rtcpPacketTypeFlags & kRtcpXrReceiverReferenceTime)
1943 {
1944 buildVal = BuildReceiverReferenceTime(rtcp_buffer,
1945 position,
1946 NTPsec,
1947 NTPfrac);
1948 if (buildVal == -1) {
1949 return -1;
1950 } else if (buildVal == -2) {
1951 return position;
1952 }
1953 }
1954 if (rtcpPacketTypeFlags & kRtcpXrDlrrReportBlock)
1955 {
1956 buildVal = BuildDlrr(rtcp_buffer, position, feedback_state.last_xr_rr);
1957 if (buildVal == -1) {
1958 return -1;
1959 } else if (buildVal == -2) {
1960 return position;
1961 }
1962 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001963 return position;
1964}
1965
1966bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
1967 return Status() == kRtcpCompound ||
1968 (rtcp_packet_type & kRtcpReport) ||
1969 (rtcp_packet_type & kRtcpSr) ||
1970 (rtcp_packet_type & kRtcpRr);
1971}
1972
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001973bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
1974 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001975 RTCPReportBlock* report_block,
1976 uint32_t* ntp_secs, uint32_t* ntp_frac) {
1977 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001978 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001979 if (!statistician->GetStatistics(&stats, true))
1980 return false;
1981 report_block->fractionLost = stats.fraction_lost;
1982 report_block->cumulativeLost = stats.cumulative_lost;
1983 report_block->extendedHighSeqNum =
1984 stats.extended_max_sequence_number;
1985 report_block->jitter = stats.jitter;
1986
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001987 // get our NTP as late as possible to avoid a race
1988 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
1989
1990 // Delay since last received report
1991 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001992 if ((feedback_state.last_rr_ntp_secs != 0) ||
1993 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001994 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1995 uint32_t now=*ntp_secs&0x0000FFFF;
1996 now <<=16;
1997 now += (*ntp_frac&0xffff0000)>>16;
1998
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001999 uint32_t receiveTime = feedback_state.last_rr_ntp_secs&0x0000FFFF;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002000 receiveTime <<=16;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002001 receiveTime += (feedback_state.last_rr_ntp_frac&0xffff0000)>>16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002002
2003 delaySinceLastReceivedSR = now-receiveTime;
2004 }
2005 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002006 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002007 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00002008}
2009
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002010int32_t
2011RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
2012 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002013{
2014 CriticalSectionScoped lock(_criticalSectionTransport);
2015 if(_cbTransport)
2016 {
2017 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
2018 {
2019 return 0;
2020 }
2021 }
2022 return -1;
2023}
2024
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002025int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002026RTCPSender::SetCSRCStatus(const bool include)
2027{
pbos@webrtc.org180e5162014-07-11 15:36:26 +00002028 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +00002029 _includeCSRCs = include;
2030 return 0;
2031}
2032
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002033int32_t
2034RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
2035 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00002036{
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002037 assert(arrLength <= kRtpCsrcSize);
niklase@google.com470e71d2011-07-07 08:21:25 +00002038 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2039
2040 for(int i = 0; i < arrLength;i++)
2041 {
2042 _CSRC[i] = arrOfCSRC[i];
2043 }
2044 _CSRCs = arrLength;
2045 return 0;
2046}
2047
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002048int32_t
2049RTCPSender::SetApplicationSpecificData(const uint8_t subType,
2050 const uint32_t name,
2051 const uint8_t* data,
2052 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002053{
2054 if(length %4 != 0)
2055 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002056 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
niklase@google.com470e71d2011-07-07 08:21:25 +00002057 return -1;
2058 }
2059 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2060
2061 if(_appData)
2062 {
2063 delete [] _appData;
2064 }
2065
2066 _appSend = true;
2067 _appSubType = subType;
2068 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002069 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002070 _appLength = length;
2071 memcpy(_appData, data, length);
2072 return 0;
2073}
2074
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002075int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002076RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2077{
2078 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2079 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2080
2081 _xrSendVoIPMetric = true;
2082 return 0;
2083}
2084
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002085void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
2086 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2087 xrSendReceiverReferenceTimeEnabled_ = enable;
2088}
2089
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00002090bool RTCPSender::RtcpXrReceiverReferenceTime() const {
2091 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2092 return xrSendReceiverReferenceTimeEnabled_;
2093}
2094
niklase@google.com470e71d2011-07-07 08:21:25 +00002095// called under critsect _criticalSectionRTCPSender
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002096int32_t RTCPSender::WriteAllReportBlocksToBuffer(
2097 uint8_t* rtcpbuffer,
2098 int pos,
2099 uint8_t& numberOfReportBlocks,
2100 const uint32_t NTPsec,
2101 const uint32_t NTPfrac) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002102 numberOfReportBlocks = external_report_blocks_.size();
2103 numberOfReportBlocks += internal_report_blocks_.size();
2104 if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002105 LOG(LS_WARNING) << "Can't fit all report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002106 return -1;
2107 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002108 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2109 while (!internal_report_blocks_.empty()) {
2110 delete internal_report_blocks_.begin()->second;
2111 internal_report_blocks_.erase(internal_report_blocks_.begin());
2112 }
2113 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2114 return pos;
2115}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002116
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002117int32_t RTCPSender::WriteReportBlocksToBuffer(
2118 uint8_t* rtcpbuffer,
2119 int32_t position,
2120 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2121 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2122 report_blocks.begin();
2123 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002124 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002125 RTCPReportBlock* reportBlock = it->second;
2126 if (reportBlock) {
2127 // Remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002128 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position, remoteSSRC);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002129 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002130
2131 // fraction lost
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002132 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002133
2134 // cumulative loss
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002135 RtpUtility::AssignUWord24ToBuffer(rtcpbuffer + position,
2136 reportBlock->cumulativeLost);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002137 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002138
2139 // extended highest seq_no, contain the highest sequence number received
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002140 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2141 reportBlock->extendedHighSeqNum);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002142 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002143
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002144 // Jitter
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002145 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2146 reportBlock->jitter);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002147 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002148
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002149 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2150 reportBlock->lastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002151 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002152
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002153 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2154 reportBlock->delaySinceLastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002155 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002156 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002157 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002158 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00002159}
2160
2161// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002162int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002163RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002164 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002165{
2166 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2167
2168 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2169 {
2170 _sendTMMBN = true;
2171 return 0;
2172 }
2173 return -1;
2174}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002175} // namespace webrtc