blob: 9991992bc3bbfa96646462d668099d612ac09d18 [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 _rembBitrate(0),
124
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000125 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000126 _tmmbr_Send(0),
127 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000128
129 _appSend(false),
130 _appSubType(0),
131 _appName(),
132 _appData(NULL),
133 _appLength(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000134
135 xrSendReceiverReferenceTimeEnabled_(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000136 _xrSendVoIPMetric(false),
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000137 _xrVoIPMetric()
niklase@google.com470e71d2011-07-07 08:21:25 +0000138{
139 memset(_CNAME, 0, sizeof(_CNAME));
140 memset(_lastSendReport, 0, sizeof(_lastSendReport));
141 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
niklase@google.com470e71d2011-07-07 08:21:25 +0000142}
143
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000144RTCPSender::~RTCPSender() {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000145 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000146
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000147 while (!internal_report_blocks_.empty()) {
148 delete internal_report_blocks_.begin()->second;
149 internal_report_blocks_.erase(internal_report_blocks_.begin());
150 }
151 while (!external_report_blocks_.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000152 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000153 external_report_blocks_.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000154 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000155 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000156 }
157 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000158 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000159 _csrcCNAMEs.begin();
160 delete it->second;
161 _csrcCNAMEs.erase(it);
162 }
163 delete _criticalSectionTransport;
164 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000165}
166
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000167int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000168RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
169{
170 CriticalSectionScoped lock(_criticalSectionTransport);
171 _cbTransport = outgoingTransport;
172 return 0;
173}
174
175RTCPMethod
176RTCPSender::Status() const
177{
178 CriticalSectionScoped lock(_criticalSectionRTCPSender);
179 return _method;
180}
181
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000182int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000183RTCPSender::SetRTCPStatus(const RTCPMethod method)
184{
185 CriticalSectionScoped lock(_criticalSectionRTCPSender);
186 if(method != kRtcpOff)
187 {
188 if(_audio)
189 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000190 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000191 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000192 } else
193 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000194 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000195 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000196 }
197 }
198 _method = method;
199 return 0;
200}
201
202bool
203RTCPSender::Sending() const
204{
205 CriticalSectionScoped lock(_criticalSectionRTCPSender);
206 return _sending;
207}
208
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000209int32_t
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000210RTCPSender::SetSendingStatus(const FeedbackState& feedback_state, bool sending)
niklase@google.com470e71d2011-07-07 08:21:25 +0000211{
212 bool sendRTCPBye = false;
213 {
214 CriticalSectionScoped lock(_criticalSectionRTCPSender);
215
216 if(_method != kRtcpOff)
217 {
218 if(sending == false && _sending == true)
219 {
220 // Trigger RTCP bye
221 sendRTCPBye = true;
222 }
223 }
224 _sending = sending;
225 }
226 if(sendRTCPBye)
227 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000228 return SendRTCP(feedback_state, kRtcpBye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000229 }
230 return 0;
231}
232
233bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000234RTCPSender::REMB() const
235{
236 CriticalSectionScoped lock(_criticalSectionRTCPSender);
237 return _REMB;
238}
239
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000240int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000241RTCPSender::SetREMBStatus(const bool enable)
242{
243 CriticalSectionScoped lock(_criticalSectionRTCPSender);
244 _REMB = enable;
245 return 0;
246}
247
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000248int32_t
249RTCPSender::SetREMBData(const uint32_t bitrate,
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000250 const std::vector<uint32_t>& ssrcs)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000251{
252 CriticalSectionScoped lock(_criticalSectionRTCPSender);
253 _rembBitrate = bitrate;
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000254 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000255
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000256 _sendREMB = true;
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000257 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
258 // throttled by the caller.
259 _nextTimeToSendRTCP = _clock->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000260 return 0;
261}
262
263bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000264RTCPSender::TMMBR() const
265{
266 CriticalSectionScoped lock(_criticalSectionRTCPSender);
267 return _TMMBR;
268}
269
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000270int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000271RTCPSender::SetTMMBRStatus(const bool enable)
272{
273 CriticalSectionScoped lock(_criticalSectionRTCPSender);
274 _TMMBR = enable;
275 return 0;
276}
277
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000278bool
279RTCPSender::IJ() const
280{
281 CriticalSectionScoped lock(_criticalSectionRTCPSender);
282 return _IJ;
283}
284
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000285int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000286RTCPSender::SetIJStatus(const bool enable)
287{
288 CriticalSectionScoped lock(_criticalSectionRTCPSender);
289 _IJ = enable;
290 return 0;
291}
292
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000293void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
pbos@webrtc.org180e5162014-07-11 15:36:26 +0000294 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000295 start_timestamp_ = start_timestamp;
296}
297
298void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
299 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000300 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000301 last_rtp_timestamp_ = rtp_timestamp;
302 if (capture_time_ms < 0) {
303 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000304 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000305 } else {
306 last_frame_capture_time_ms_ = capture_time_ms;
307 }
308}
309
niklase@google.com470e71d2011-07-07 08:21:25 +0000310void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000311RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000312{
313 CriticalSectionScoped lock(_criticalSectionRTCPSender);
314
315 if(_SSRC != 0)
316 {
317 // not first SetSSRC, probably due to a collision
318 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000319 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000320 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000321 }
322 _SSRC = ssrc;
323}
324
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000325void RTCPSender::SetRemoteSSRC(uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000326{
327 CriticalSectionScoped lock(_criticalSectionRTCPSender);
328 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000329}
330
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000331int32_t
332RTCPSender::SetCameraDelay(const int32_t delayMS)
333{
334 CriticalSectionScoped lock(_criticalSectionRTCPSender);
335 if(delayMS > 1000 || delayMS < -1000)
336 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000337 LOG(LS_WARNING) << "Delay can't be larger than 1 second: "
338 << delayMS << " ms";
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000339 return -1;
340 }
341 _cameraDelayMS = delayMS;
342 return 0;
343}
344
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000345int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000346 if (!cName)
347 return -1;
348
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000349 CriticalSectionScoped lock(_criticalSectionRTCPSender);
350 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
351 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
352 return 0;
353}
354
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000355int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
356 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000357 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000358 CriticalSectionScoped lock(_criticalSectionRTCPSender);
359 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
360 return -1;
361 }
362 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000363 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
364 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000365 _csrcCNAMEs[SSRC] = ptr;
366 return 0;
367}
368
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000369int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000370 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000371 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000372 _csrcCNAMEs.find(SSRC);
373
374 if (it == _csrcCNAMEs.end()) {
375 return -1;
376 }
377 delete it->second;
378 _csrcCNAMEs.erase(it);
379 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000380}
381
382bool
383RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
384{
385/*
386 For audio we use a fix 5 sec interval
387
388 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000389 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
390 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000391
392
393From RFC 3550
394
395 MAX RTCP BW is 5% if the session BW
396 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000397 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000398
399 The RECOMMENDED value for the reduced minimum in seconds is 360
400 divided by the session bandwidth in kilobits/second. This minimum
401 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
402
403 If the participant has not yet sent an RTCP packet (the variable
404 initial is true), the constant Tmin is set to 2.5 seconds, else it
405 is set to 5 seconds.
406
407 The interval between RTCP packets is varied randomly over the
408 range [0.5,1.5] times the calculated interval to avoid unintended
409 synchronization of all participants
410
411 if we send
412 If the participant is a sender (we_sent true), the constant C is
413 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
414 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
415 number of senders.
416
417 if we receive only
418 If we_sent is not true, the constant C is set
419 to the average RTCP packet size divided by 75% of the RTCP
420 bandwidth. The constant n is set to the number of receivers
421 (members - senders). If the number of senders is greater than
422 25%, senders and receivers are treated together.
423
424 reconsideration NOT required for peer-to-peer
425 "timer reconsideration" is
426 employed. This algorithm implements a simple back-off mechanism
427 which causes users to hold back RTCP packet transmission if the
428 group sizes are increasing.
429
430 n = number of members
431 C = avg_size/(rtcpBW/4)
432
433 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
434
435 4. The calculated interval T is set to a number uniformly distributed
436 between 0.5 and 1.5 times the deterministic calculated interval.
437
438 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
439 for the fact that the timer reconsideration algorithm converges to
440 a value of the RTCP bandwidth below the intended average
441*/
442
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000443 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000444
445 CriticalSectionScoped lock(_criticalSectionRTCPSender);
446
niklase@google.com470e71d2011-07-07 08:21:25 +0000447 if(_method == kRtcpOff)
448 {
449 return false;
450 }
451
niklase@google.com470e71d2011-07-07 08:21:25 +0000452 if(!_audio && sendKeyframeBeforeRTP)
453 {
454 // for video key-frames we want to send the RTCP before the large key-frame
455 // if we have a 100 ms margin
456 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
457 }
458
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000459 if(now >= _nextTimeToSendRTCP)
niklase@google.com470e71d2011-07-07 08:21:25 +0000460 {
461 return true;
462
463 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
464 {
465 // wrap
466 return true;
467 }
468 return false;
469}
470
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000471uint32_t
472RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000473{
474 CriticalSectionScoped lock(_criticalSectionRTCPSender);
475
476 lastRTCPTime = _lastRTCPTime[0];
477 return _lastSendReport[0];
478}
479
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000480uint32_t
481RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000482{
483 CriticalSectionScoped lock(_criticalSectionRTCPSender);
484
485 // This is only saved when we are the sender
486 if((_lastSendReport[0] == 0) || (sendReport == 0))
487 {
488 return 0; // will be ignored
489 } else
490 {
491 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
492 {
493 if( _lastSendReport[i] == sendReport)
494 {
495 return _lastRTCPTime[i];
496 }
497 }
498 }
499 return 0;
500}
501
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000502bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
503 int64_t* time_ms) const {
504 CriticalSectionScoped lock(_criticalSectionRTCPSender);
505
506 if (last_xr_rr_.empty()) {
507 return false;
508 }
509 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
510 if (it == last_xr_rr_.end()) {
511 return false;
512 }
513 *time_ms = it->second;
514 return true;
515}
516
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000517void RTCPSender::GetPacketTypeCounter(
518 RtcpPacketTypeCounter* packet_counter) const {
519 CriticalSectionScoped lock(_criticalSectionRTCPSender);
520 *packet_counter = packet_type_counter_;
521}
522
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000523int32_t RTCPSender::AddExternalReportBlock(
524 uint32_t SSRC,
525 const RTCPReportBlock* reportBlock) {
526 CriticalSectionScoped lock(_criticalSectionRTCPSender);
527 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
528}
529
530int32_t RTCPSender::AddReportBlock(
531 uint32_t SSRC,
532 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
533 const RTCPReportBlock* reportBlock) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000534 assert(reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000535
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000536 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000537 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000538 return -1;
539 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000540 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000541 report_blocks->find(SSRC);
542 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000543 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000544 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000545 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000546 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
547 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000548 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000549 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000550}
551
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000552int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000553 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000554
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000555 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000556 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000557
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000558 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000559 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000560 }
561 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000562 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000563 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000564}
565
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000566int32_t RTCPSender::BuildSR(const FeedbackState& feedback_state,
567 uint8_t* rtcpbuffer,
568 int& pos,
569 uint32_t NTPsec,
570 uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000571{
572 // sanity
573 if(pos + 52 >= IP_PACKET_SIZE)
574 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000575 LOG(LS_WARNING) << "Failed to build Sender Report.";
niklase@google.com470e71d2011-07-07 08:21:25 +0000576 return -2;
577 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000578 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000579
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000580 uint32_t posNumberOfReportBlocks = pos;
581 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000582
583 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000584 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000585
586 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
587 {
588 // shift old
589 _lastSendReport[i+1] = _lastSendReport[i];
590 _lastRTCPTime[i+1] =_lastRTCPTime[i];
591 }
592
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000593 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000594 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000595
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000596 // The timestamp of this RTCP packet should be estimated as the timestamp of
597 // the frame being captured at this moment. We are calculating that
598 // timestamp as the last frame's timestamp + the time since the last frame
599 // was captured.
pbos@webrtc.org180e5162014-07-11 15:36:26 +0000600 RTPtime = start_timestamp_ + last_rtp_timestamp_ +
601 (_clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
602 (feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000603
604 // Add sender data
605 // Save for our length field
606 pos++;
607 pos++;
608
609 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000610 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000611 pos += 4;
612 // NTP
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000613 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000614 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000615 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000616 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000617 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, RTPtime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000618 pos += 4;
619
620 //sender's packet count
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000621 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000622 feedback_state.packets_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000623 pos += 4;
624
625 //sender's octet count
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000626 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000627 feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000628 pos += 4;
629
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000630 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000631 int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
632 numberOfReportBlocks,
633 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000634 if(retVal < 0)
635 {
636 //
637 return retVal ;
638 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000639 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000640 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
641
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000642 uint16_t len = uint16_t((pos/4) -1);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000643 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000644 return 0;
645}
646
647
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000648int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000649 size_t lengthCname = strlen(_CNAME);
650 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000651
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000652 // sanity
653 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000654 LOG(LS_WARNING) << "Failed to build SDEC.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000655 return -2;
656 }
657 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000658
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000659 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000660 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
661 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000662
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000663 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000664 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000665 pos++;
666 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000667
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000668 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000669 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000670 pos += 4;
671
672 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000673 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000674
675 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000676 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000677
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000678 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000679
680 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
681 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000682 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000683
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000684 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000685 // We must have a zero field even if we have an even multiple of 4 bytes
686 if ((pos % 4) == 0) {
687 padding++;
688 rtcpbuffer[pos++]=0;
689 }
690 while ((pos % 4) != 0) {
691 padding++;
692 rtcpbuffer[pos++]=0;
693 }
694 SDESLength += padding;
695
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000696 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000697 _csrcCNAMEs.begin();
698
699 for(; it != _csrcCNAMEs.end(); it++) {
700 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000701 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000702
703 // Add SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000704 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000705 pos += 4;
706
707 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000708 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000709
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000710 size_t length = strlen(cname->name);
711 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000712
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000713 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000714 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000715
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000716 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000717
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000718 pos += length;
719 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000720 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000721
722 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000723 if((pos % 4) == 0){
724 padding++;
725 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000726 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000727 while((pos % 4) != 0){
728 padding++;
729 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000730 }
731 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000732 }
733 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000734 uint16_t buffer_length = (SDESLength / 4) - 1;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000735 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos, buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000736 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000737}
738
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000739int32_t
740RTCPSender::BuildRR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000741 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000742 const uint32_t NTPsec,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000743 const uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000744{
745 // sanity one block
746 if(pos + 32 >= IP_PACKET_SIZE)
747 {
748 return -2;
749 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000750 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000751
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000752 rtcpbuffer[pos++]=(uint8_t)0x80;
753 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000754
755 // Save for our length field
756 pos++;
757 pos++;
758
759 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000760 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000761 pos += 4;
762
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000763 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000764 int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
765 numberOfReportBlocks,
766 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000767 if(retVal < 0)
768 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000769 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000770 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000771 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000772 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
773
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000774 uint16_t len = uint16_t((pos)/4 -1);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000775 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000776 return 0;
777}
778
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000779// From RFC 5450: Transmission Time Offsets in RTP Streams.
780// 0 1 2 3
781// 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
782// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
783// hdr |V=2|P| RC | PT=IJ=195 | length |
784// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
785// | inter-arrival jitter |
786// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
787// . .
788// . .
789// . .
790// | inter-arrival jitter |
791// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
792//
793// If present, this RTCP packet must be placed after a receiver report
794// (inside a compound RTCP packet), and MUST have the same value for RC
795// (reception report count) as the receiver report.
796
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000797int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000798RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000799 uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000800 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000801 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000802{
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000803 if (external_report_blocks_.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000804 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000805 // TODO(andresp): Remove external report blocks since they are not
806 // supported.
807 LOG(LS_ERROR) << "Handling of external report blocks not implemented.";
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000808 return 0;
809 }
810
811 // sanity
812 if(pos + 8 >= IP_PACKET_SIZE)
813 {
814 return -2;
815 }
816 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000817 uint8_t RC = 1;
818 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
819 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000820
821 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000822 rtcpbuffer[pos++]=(uint8_t)0;
823 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000824
825 // Add inter-arrival jitter
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000826 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
827 jitterTransmissionTimeOffset);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000828 pos += 4;
829 return 0;
830}
831
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000832int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000833RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000834{
835 // sanity
836 if(pos + 12 >= IP_PACKET_SIZE)
837 {
838 return -2;
839 }
840 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000841 uint8_t FMT = 1;
842 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
843 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000844
845 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000846 rtcpbuffer[pos++]=(uint8_t)0;
847 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000848
849 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000850 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000851 pos += 4;
852
853 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000854 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000855 pos += 4;
856 return 0;
857}
858
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000859int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000860 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000861 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000862 // sanity
863 if(pos + 20 >= IP_PACKET_SIZE) {
864 return -2;
865 }
866 if (!repeat) {
867 _sequenceNumberFIR++; // do not increase if repetition
868 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000869
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000870 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000871 uint8_t FMT = 4;
872 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
873 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000874
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000875 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000876 rtcpbuffer[pos++] = (uint8_t)0;
877 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000878
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000879 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000880 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000881 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000882
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000883 // RFC 5104 4.3.1.2. Semantics
884 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000885 rtcpbuffer[pos++] = (uint8_t)0;
886 rtcpbuffer[pos++] = (uint8_t)0;
887 rtcpbuffer[pos++] = (uint8_t)0;
888 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000889
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000890 // Additional Feedback Control Information (FCI)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000891 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000892 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000893
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000894 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
895 rtcpbuffer[pos++] = (uint8_t)0;
896 rtcpbuffer[pos++] = (uint8_t)0;
897 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000898 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000899}
900
901/*
902 0 1 2 3
903 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
904 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
905 | First | Number | PictureID |
906 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
907*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000908int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000909RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000910{
911 // sanity
912 if(pos + 16 >= IP_PACKET_SIZE)
913 {
914 return -2;
915 }
916 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000917 uint8_t FMT = 2;
918 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
919 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000920
921 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000922 rtcpbuffer[pos++]=(uint8_t)0;
923 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000924
925 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000926 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000927 pos += 4;
928
929 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000930 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000931 pos += 4;
932
933 // Add first, number & picture ID 6 bits
934 // first = 0, 13 - bits
935 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000936 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000937 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, sliField);
niklase@google.com470e71d2011-07-07 08:21:25 +0000938 pos += 4;
939 return 0;
940}
941
942/*
943 0 1 2 3
944 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
945 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
946 | PB |0| Payload Type| Native RPSI bit string |
947 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
948 | defined per codec ... | Padding (0) |
949 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
950*/
951/*
952* Note: not generic made for VP8
953*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000954int32_t
955RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000956 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000957 const uint64_t pictureID,
958 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +0000959{
960 // sanity
961 if(pos + 24 >= IP_PACKET_SIZE)
962 {
963 return -2;
964 }
965 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000966 uint8_t FMT = 3;
967 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
968 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000969
970 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000971 uint32_t bitsRequired = 7;
972 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000973 while((pictureID>>bitsRequired) > 0)
974 {
975 bitsRequired += 7;
976 bytesRequired++;
977 }
978
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000979 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +0000980 if(bytesRequired > 6)
981 {
982 size = 5;
983 } else if(bytesRequired > 2)
984 {
985 size = 4;
986 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000987 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000988 rtcpbuffer[pos++]=size;
989
990 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000991 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000992 pos += 4;
993
994 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000995 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000996 pos += 4;
997
998 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000999 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001000 if(paddingBytes == 4)
1001 {
1002 paddingBytes = 0;
1003 }
1004 // add padding length in bits
1005 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1006 pos++;
1007
1008 // add payload type
1009 rtcpbuffer[pos] = payloadType;
1010 pos++;
1011
1012 // add picture ID
1013 for(int i = bytesRequired-1; i > 0; i--)
1014 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001015 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001016 pos++;
1017 }
1018 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001019 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001020 pos++;
1021
1022 // add padding
1023 for(int j = 0; j <paddingBytes; j++)
1024 {
1025 rtcpbuffer[pos] = 0;
1026 pos++;
1027 }
1028 return 0;
1029}
1030
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001031int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001032RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001033{
1034 // sanity
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001035 if(pos + 20 + 4 * remb_ssrcs_.size() >= IP_PACKET_SIZE)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001036 {
1037 return -2;
1038 }
1039 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001040 uint8_t FMT = 15;
1041 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1042 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001043
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001044 rtcpbuffer[pos++]=(uint8_t)0;
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001045 rtcpbuffer[pos++]=remb_ssrcs_.size() + 4;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001046
1047 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001048 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001049 pos += 4;
1050
1051 // Remote SSRC must be 0
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001052 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, 0);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001053 pos += 4;
1054
1055 rtcpbuffer[pos++]='R';
1056 rtcpbuffer[pos++]='E';
1057 rtcpbuffer[pos++]='M';
1058 rtcpbuffer[pos++]='B';
1059
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001060 rtcpbuffer[pos++] = remb_ssrcs_.size();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001061 // 6 bit Exp
1062 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001063 uint8_t brExp = 0;
1064 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001065 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001066 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001067 {
1068 brExp = i;
1069 break;
1070 }
1071 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001072 const uint32_t brMantissa = (_rembBitrate >> brExp);
1073 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1074 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1075 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001076
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001077 for (size_t i = 0; i < remb_ssrcs_.size(); i++)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001078 {
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001079 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, remb_ssrcs_[i]);
1080 pos += 4;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001081 }
1082 return 0;
1083}
1084
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001085void
1086RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001087{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001088 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001089 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001090}
1091
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001092int32_t RTCPSender::BuildTMMBR(ModuleRtpRtcpImpl* rtp_rtcp_module,
1093 uint8_t* rtcpbuffer,
1094 int& pos) {
1095 if (rtp_rtcp_module == NULL)
1096 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001097 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1098 // If the sender is an owner of the TMMBN -> send TMMBR
1099 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1100
niklase@google.com470e71d2011-07-07 08:21:25 +00001101 // get current bounding set from RTCP receiver
1102 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001103 // store in candidateSet, allocates one extra slot
1104 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001105
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001106 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1107 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1108 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001109 int32_t lengthOfBoundingSet =
1110 rtp_rtcp_module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001111
1112 if(lengthOfBoundingSet > 0)
1113 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001114 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001115 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001116 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1117 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001118 {
1119 // do not send the same tuple
1120 return 0;
1121 }
1122 }
1123 if(!tmmbrOwner)
1124 {
1125 // use received bounding set as candidate set
1126 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001127 candidateSet->SetEntry(lengthOfBoundingSet,
1128 _tmmbr_Send,
1129 _packetOH_Send,
1130 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001131 int numCandidates = lengthOfBoundingSet+ 1;
1132
1133 // find bounding set
1134 TMMBRSet* boundingSet = NULL;
1135 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1136 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1137 {
1138 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1139 }
1140 if(!tmmbrOwner)
1141 {
1142 // did not enter bounding set, no meaning to send this request
1143 return 0;
1144 }
1145 }
1146 }
1147
1148 if(_tmmbr_Send)
1149 {
1150 // sanity
1151 if(pos + 20 >= IP_PACKET_SIZE)
1152 {
1153 return -2;
1154 }
1155 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001156 uint8_t FMT = 3;
1157 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1158 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001159
1160 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001161 rtcpbuffer[pos++]=(uint8_t)0;
1162 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001163
1164 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001165 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001166 pos += 4;
1167
1168 // RFC 5104 4.2.1.2. Semantics
1169
1170 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001171 rtcpbuffer[pos++]=(uint8_t)0;
1172 rtcpbuffer[pos++]=(uint8_t)0;
1173 rtcpbuffer[pos++]=(uint8_t)0;
1174 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001175
1176 // Additional Feedback Control Information (FCI)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001177 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001178 pos += 4;
1179
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001180 uint32_t bitRate = _tmmbr_Send*1000;
1181 uint32_t mmbrExp = 0;
1182 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001183 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001184 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001185 {
1186 mmbrExp = i;
1187 break;
1188 }
1189 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001190 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001191
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001192 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1193 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1194 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1195 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001196 }
1197 return 0;
1198}
1199
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001200int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001201RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001202{
1203 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1204 if(boundingSet == NULL)
1205 {
1206 return -1;
1207 }
1208 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001209 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001210 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001211 LOG(LS_WARNING) << "Failed to build TMMBN.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001212 return -2;
1213 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001214 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001215 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001216 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1217 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001218
1219 //Add length later
1220 int posLength = pos;
1221 pos++;
1222 pos++;
1223
1224 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001225 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001226 pos += 4;
1227
1228 // RFC 5104 4.2.2.2. Semantics
1229
1230 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001231 rtcpbuffer[pos++]=(uint8_t)0;
1232 rtcpbuffer[pos++]=(uint8_t)0;
1233 rtcpbuffer[pos++]=(uint8_t)0;
1234 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001235
1236 // Additional Feedback Control Information (FCI)
1237 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001238 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001239 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001240 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001241 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001242 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001243 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, tmmbrSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001244 pos += 4;
1245
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001246 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1247 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001248 for(int i=0; i<64; i++)
1249 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001250 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001251 {
1252 mmbrExp = i;
1253 break;
1254 }
1255 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001256 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1257 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001258
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001259 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1260 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1261 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1262 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001263 numBoundingSet++;
1264 }
1265 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001266 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1267 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1268 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001269 return 0;
1270}
1271
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001272int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001273RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001274{
1275 // sanity
1276 if(_appData == NULL)
1277 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001278 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001279 return -1;
1280 }
1281 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1282 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001283 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001284 return -2;
1285 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001286 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001287
1288 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001289 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001290
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001291 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1292 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1293 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001294
1295 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001296 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001297 pos += 4;
1298
1299 // Add our application name
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001300 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _appName);
niklase@google.com470e71d2011-07-07 08:21:25 +00001301 pos += 4;
1302
1303 // Add the data
1304 memcpy(rtcpbuffer +pos, _appData,_appLength);
1305 pos += _appLength;
1306 return 0;
1307}
1308
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001309int32_t
1310RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001311 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001312 const int32_t nackSize,
1313 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001314 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001315{
1316 // sanity
1317 if(pos + 16 >= IP_PACKET_SIZE)
1318 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001319 LOG(LS_WARNING) << "Failed to build NACK.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001320 return -2;
1321 }
1322
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001323 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001324 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001325 uint8_t FMT = 1;
1326 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1327 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001328
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001329 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001330 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001331 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001332
1333 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001334 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001335 pos += 4;
1336
1337 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001338 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001339 pos += 4;
1340
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001341 // Build NACK bitmasks and write them to the RTCP message.
1342 // The nack list should be sorted and not contain duplicates if one
1343 // wants to build the smallest rtcp nack packet.
1344 int numOfNackFields = 0;
1345 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1346 (IP_PACKET_SIZE - pos) / 4);
1347 int i = 0;
1348 while (i < nackSize && numOfNackFields < maxNackFields) {
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001349 uint16_t nack = nackList[i++];
1350 uint16_t bitmask = 0;
1351 while (i < nackSize) {
1352 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1353 if (shift >= 0 && shift <= 15) {
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001354 bitmask |= (1 << shift);
1355 ++i;
1356 } else {
1357 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001358 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001359 }
1360 // Write the sequence number and the bitmask to the packet.
1361 assert(pos + 4 < IP_PACKET_SIZE);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001362 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001363 pos += 2;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001364 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001365 pos += 2;
1366 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001367 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001368 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001369
1370 if (i != nackSize) {
1371 LOG(LS_WARNING) << "Nack list too large for one packet.";
1372 }
1373
1374 // Report stats.
1375 NACKStringBuilder stringBuilder;
1376 for (int idx = 0; idx < i; ++idx) {
1377 stringBuilder.PushNACK(nackList[idx]);
1378 nack_stats_.ReportRequest(nackList[idx]);
1379 }
edjee@google.com79b02892013-04-04 19:43:34 +00001380 *nackString = stringBuilder.GetResult();
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001381 packet_type_counter_.nack_requests = nack_stats_.requests();
1382 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
niklase@google.com470e71d2011-07-07 08:21:25 +00001383 return 0;
1384}
1385
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001386int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001387RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001388{
1389 // sanity
1390 if(pos + 8 >= IP_PACKET_SIZE)
1391 {
1392 return -2;
1393 }
1394 if(_includeCSRCs)
1395 {
1396 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001397 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1398 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001399
1400 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001401 rtcpbuffer[pos++]=(uint8_t)0;
1402 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001403
1404 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001405 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001406 pos += 4;
1407
1408 // add CSRCs
1409 for(int i = 0; i < _CSRCs; i++)
1410 {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001411 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _CSRC[i]);
niklase@google.com470e71d2011-07-07 08:21:25 +00001412 pos += 4;
1413 }
1414 } else
1415 {
1416 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001417 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1418 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001419
1420 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001421 rtcpbuffer[pos++]=(uint8_t)0;
1422 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001423
1424 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001425 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001426 pos += 4;
1427 }
1428 return 0;
1429}
1430
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001431int32_t RTCPSender::BuildReceiverReferenceTime(uint8_t* buffer,
1432 int& pos,
1433 uint32_t ntp_sec,
1434 uint32_t ntp_frac) {
1435 const int kRrTimeBlockLength = 20;
1436 if (pos + kRrTimeBlockLength >= IP_PACKET_SIZE) {
1437 return -2;
1438 }
1439
1440 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) {
1441 last_xr_rr_.erase(last_xr_rr_.begin());
1442 }
1443 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
1444 RTCPUtility::MidNtp(ntp_sec, ntp_frac),
1445 Clock::NtpToMs(ntp_sec, ntp_frac)));
1446
1447 // Add XR header.
1448 buffer[pos++] = 0x80;
1449 buffer[pos++] = 207;
1450 buffer[pos++] = 0; // XR packet length.
1451 buffer[pos++] = 4; // XR packet length.
1452
1453 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001454 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001455 pos += 4;
1456
1457 // 0 1 2 3
1458 // 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
1459 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1460 // | BT=4 | reserved | block length = 2 |
1461 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1462 // | NTP timestamp, most significant word |
1463 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1464 // | NTP timestamp, least significant word |
1465 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1466
1467 // Add Receiver Reference Time Report block.
1468 buffer[pos++] = 4; // BT.
1469 buffer[pos++] = 0; // Reserved.
1470 buffer[pos++] = 0; // Block length.
1471 buffer[pos++] = 2; // Block length.
1472
1473 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001474 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_sec);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001475 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001476 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001477 pos += 4;
1478
1479 return 0;
1480}
1481
1482int32_t RTCPSender::BuildDlrr(uint8_t* buffer,
1483 int& pos,
1484 const RtcpReceiveTimeInfo& info) {
1485 const int kDlrrBlockLength = 24;
1486 if (pos + kDlrrBlockLength >= IP_PACKET_SIZE) {
1487 return -2;
1488 }
1489
1490 // Add XR header.
1491 buffer[pos++] = 0x80;
1492 buffer[pos++] = 207;
1493 buffer[pos++] = 0; // XR packet length.
1494 buffer[pos++] = 5; // XR packet length.
1495
1496 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001497 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001498 pos += 4;
1499
1500 // 0 1 2 3
1501 // 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
1502 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1503 // | BT=5 | reserved | block length |
1504 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1505 // | SSRC_1 (SSRC of first receiver) | sub-
1506 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1507 // | last RR (LRR) | 1
1508 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1509 // | delay since last RR (DLRR) |
1510 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1511 // | SSRC_2 (SSRC of second receiver) | sub-
1512 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1513 // : ... : 2
1514
1515 // Add DLRR sub block.
1516 buffer[pos++] = 5; // BT.
1517 buffer[pos++] = 0; // Reserved.
1518 buffer[pos++] = 0; // Block length.
1519 buffer[pos++] = 3; // Block length.
1520
1521 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001522 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.sourceSSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001523 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001524 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.lastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001525 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001526 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.delaySinceLastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001527 pos += 4;
1528
1529 return 0;
1530}
1531
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001532int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001533RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001534{
1535 // sanity
1536 if(pos + 44 >= IP_PACKET_SIZE)
1537 {
1538 return -2;
1539 }
1540
1541 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001542 rtcpbuffer[pos++]=(uint8_t)0x80;
1543 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001544
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001545 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001546
1547 // handle length later on
1548 pos++;
1549 pos++;
1550
1551 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001552 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001553 pos += 4;
1554
1555 // Add a VoIP metrics block
1556 rtcpbuffer[pos++]=7;
1557 rtcpbuffer[pos++]=0;
1558 rtcpbuffer[pos++]=0;
1559 rtcpbuffer[pos++]=8;
1560
1561 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001562 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001563 pos += 4;
1564
1565 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1566 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1567 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1568 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1569
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001570 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1571 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1572 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1573 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001574
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001575 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1576 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1577 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1578 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001579
1580 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1581 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1582 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1583 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1584
1585 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1586 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1587 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1588 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1589
1590 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1591 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001592 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1593 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001594
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001595 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1596 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1597 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1598 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001599
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001600 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1601 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001602 return 0;
1603}
1604
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001605int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
1606 uint32_t packetTypeFlags,
1607 int32_t nackSize,
1608 const uint16_t* nackList,
1609 bool repeat,
1610 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001611 {
1612 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1613 if(_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001614 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001615 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001616 return -1;
1617 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001618 }
1619 uint8_t rtcp_buffer[IP_PACKET_SIZE];
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001620 int rtcp_length = PrepareRTCP(feedback_state,
1621 packetTypeFlags,
1622 nackSize,
1623 nackList,
1624 repeat,
1625 pictureID,
1626 rtcp_buffer,
1627 IP_PACKET_SIZE);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001628 if (rtcp_length < 0) {
1629 return -1;
1630 }
1631 // Sanity don't send empty packets.
1632 if (rtcp_length == 0)
1633 {
1634 return -1;
1635 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001636 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001637}
1638
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001639int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
1640 uint32_t packetTypeFlags,
1641 int32_t nackSize,
1642 const uint16_t* nackList,
1643 bool repeat,
1644 uint64_t pictureID,
1645 uint8_t* rtcp_buffer,
1646 int buffer_size) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001647 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1648 // Collect the received information.
1649 uint32_t NTPsec = 0;
1650 uint32_t NTPfrac = 0;
1651 uint32_t jitterTransmissionOffset = 0;
1652 int position = 0;
1653
1654 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1655
1656 if(_TMMBR ) // Attach TMMBR to send and receive reports.
1657 {
1658 rtcpPacketTypeFlags |= kRtcpTmmbr;
1659 }
1660 if(_appSend)
1661 {
1662 rtcpPacketTypeFlags |= kRtcpApp;
1663 _appSend = false;
1664 }
1665 if(_REMB && _sendREMB)
1666 {
1667 // Always attach REMB to SR if that is configured. Note that REMB is
1668 // only sent on one of the RTP modules in the REMB group.
1669 rtcpPacketTypeFlags |= kRtcpRemb;
1670 }
1671 if(_xrSendVoIPMetric)
1672 {
1673 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1674 _xrSendVoIPMetric = false;
1675 }
1676 if(_sendTMMBN) // Set when having received a TMMBR.
1677 {
1678 rtcpPacketTypeFlags |= kRtcpTmmbn;
1679 _sendTMMBN = false;
1680 }
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001681 if (rtcpPacketTypeFlags & kRtcpReport)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001682 {
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001683 if (xrSendReceiverReferenceTimeEnabled_ && !_sending)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001684 {
1685 rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
1686 }
1687 if (feedback_state.has_last_xr_rr)
1688 {
1689 rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
1690 }
1691 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001692 if(_method == kRtcpCompound)
1693 {
1694 if(_sending)
1695 {
1696 rtcpPacketTypeFlags |= kRtcpSr;
1697 } else
1698 {
1699 rtcpPacketTypeFlags |= kRtcpRr;
1700 }
1701 } else if(_method == kRtcpNonCompound)
1702 {
1703 if(rtcpPacketTypeFlags & kRtcpReport)
1704 {
1705 if(_sending)
1706 {
1707 rtcpPacketTypeFlags |= kRtcpSr;
1708 } else
1709 {
1710 rtcpPacketTypeFlags |= kRtcpRr;
1711 }
1712 }
1713 }
1714 if( rtcpPacketTypeFlags & kRtcpRr ||
1715 rtcpPacketTypeFlags & kRtcpSr)
1716 {
1717 // generate next time to send a RTCP report
1718 // seeded from RTP constructor
1719 int32_t random = rand() % 1000;
1720 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1721
1722 if(_audio)
1723 {
1724 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1725 (RTCP_INTERVAL_AUDIO_MS*random/1000);
1726 }else
1727 {
1728 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1729 if(_sending)
1730 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001731 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1732 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1733 if (send_bitrate_kbit != 0)
1734 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001735 }
1736 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1737 {
1738 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1739 }
1740 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1741 }
1742 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1743 }
1744
1745 // If the data does not fit in the packet we fill it as much as possible.
1746 int32_t buildVal = 0;
1747
1748 // We need to send our NTP even if we haven't received any reports.
1749 _clock->CurrentNtp(NTPsec, NTPfrac);
1750 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1751 StatisticianMap statisticians =
1752 receive_statistics_->GetActiveStatisticians();
1753 if (!statisticians.empty()) {
1754 StatisticianMap::const_iterator it;
1755 int i;
1756 for (it = statisticians.begin(), i = 0; it != statisticians.end();
1757 ++it, ++i) {
1758 RTCPReportBlock report_block;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001759 if (PrepareReport(
1760 feedback_state, it->second, &report_block, &NTPsec, &NTPfrac))
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001761 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1762 }
1763 if (_IJ && !statisticians.empty()) {
1764 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1765 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001766 }
1767 }
1768
1769 if(rtcpPacketTypeFlags & kRtcpSr)
1770 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001771 buildVal = BuildSR(feedback_state, rtcp_buffer, position, NTPsec, NTPfrac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001772 if (buildVal == -1) {
1773 return -1;
1774 } else if (buildVal == -2) {
1775 return position;
1776 }
1777 buildVal = BuildSDEC(rtcp_buffer, position);
1778 if (buildVal == -1) {
1779 return -1;
1780 } else if (buildVal == -2) {
1781 return position;
1782 }
1783 }else if(rtcpPacketTypeFlags & kRtcpRr)
1784 {
1785 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1786 if (buildVal == -1) {
1787 return -1;
1788 } else if (buildVal == -2) {
1789 return position;
1790 }
1791 // only of set
1792 if(_CNAME[0] != 0)
1793 {
1794 buildVal = BuildSDEC(rtcp_buffer, position);
1795 if (buildVal == -1) {
1796 return -1;
1797 }
1798 }
1799 }
1800 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1801 {
1802 // If present, this RTCP packet must be placed after a
1803 // receiver report.
1804 buildVal = BuildExtendedJitterReport(rtcp_buffer,
1805 position,
1806 jitterTransmissionOffset);
1807 if (buildVal == -1) {
1808 return -1;
1809 } else if (buildVal == -2) {
1810 return position;
1811 }
1812 }
1813 if(rtcpPacketTypeFlags & kRtcpPli)
1814 {
1815 buildVal = BuildPLI(rtcp_buffer, position);
1816 if (buildVal == -1) {
1817 return -1;
1818 } else if (buildVal == -2) {
1819 return position;
1820 }
1821 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001822 ++packet_type_counter_.pli_packets;
1823 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC,
1824 packet_type_counter_.pli_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001825 }
1826 if(rtcpPacketTypeFlags & kRtcpFir)
1827 {
1828 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1829 if (buildVal == -1) {
1830 return -1;
1831 } else if (buildVal == -2) {
1832 return position;
1833 }
1834 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001835 ++packet_type_counter_.fir_packets;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001836 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001837 packet_type_counter_.fir_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001838 }
1839 if(rtcpPacketTypeFlags & kRtcpSli)
1840 {
1841 buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1842 if (buildVal == -1) {
1843 return -1;
1844 } else if (buildVal == -2) {
1845 return position;
1846 }
1847 }
1848 if(rtcpPacketTypeFlags & kRtcpRpsi)
1849 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001850 const int8_t payloadType = feedback_state.send_payload_type;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001851 if (payloadType == -1) {
1852 return -1;
1853 }
1854 buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1855 (uint8_t)payloadType);
1856 if (buildVal == -1) {
1857 return -1;
1858 } else if (buildVal == -2) {
1859 return position;
1860 }
1861 }
1862 if(rtcpPacketTypeFlags & kRtcpRemb)
1863 {
1864 buildVal = BuildREMB(rtcp_buffer, position);
1865 if (buildVal == -1) {
1866 return -1;
1867 } else if (buildVal == -2) {
1868 return position;
1869 }
1870 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1871 }
1872 if(rtcpPacketTypeFlags & kRtcpBye)
1873 {
1874 buildVal = BuildBYE(rtcp_buffer, position);
1875 if (buildVal == -1) {
1876 return -1;
1877 } else if (buildVal == -2) {
1878 return position;
1879 }
1880 }
1881 if(rtcpPacketTypeFlags & kRtcpApp)
1882 {
1883 buildVal = BuildAPP(rtcp_buffer, position);
1884 if (buildVal == -1) {
1885 return -1;
1886 } else if (buildVal == -2) {
1887 return position;
1888 }
1889 }
1890 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1891 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001892 buildVal = BuildTMMBR(feedback_state.module, rtcp_buffer, position);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001893 if (buildVal == -1) {
1894 return -1;
1895 } else if (buildVal == -2) {
1896 return position;
1897 }
1898 }
1899 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1900 {
1901 buildVal = BuildTMMBN(rtcp_buffer, position);
1902 if (buildVal == -1) {
1903 return -1;
1904 } else if (buildVal == -2) {
1905 return position;
1906 }
1907 }
1908 if(rtcpPacketTypeFlags & kRtcpNack)
1909 {
1910 std::string nackString;
1911 buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
1912 &nackString);
1913 if (buildVal == -1) {
1914 return -1;
1915 } else if (buildVal == -2) {
1916 return position;
1917 }
1918 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
1919 "nacks", TRACE_STR_COPY(nackString.c_str()));
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001920 ++packet_type_counter_.nack_packets;
1921 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC,
1922 packet_type_counter_.nack_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001923 }
1924 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1925 {
1926 buildVal = BuildVoIPMetric(rtcp_buffer, position);
1927 if (buildVal == -1) {
1928 return -1;
1929 } else if (buildVal == -2) {
1930 return position;
1931 }
1932 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001933 if (rtcpPacketTypeFlags & kRtcpXrReceiverReferenceTime)
1934 {
1935 buildVal = BuildReceiverReferenceTime(rtcp_buffer,
1936 position,
1937 NTPsec,
1938 NTPfrac);
1939 if (buildVal == -1) {
1940 return -1;
1941 } else if (buildVal == -2) {
1942 return position;
1943 }
1944 }
1945 if (rtcpPacketTypeFlags & kRtcpXrDlrrReportBlock)
1946 {
1947 buildVal = BuildDlrr(rtcp_buffer, position, feedback_state.last_xr_rr);
1948 if (buildVal == -1) {
1949 return -1;
1950 } else if (buildVal == -2) {
1951 return position;
1952 }
1953 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001954 return position;
1955}
1956
1957bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
1958 return Status() == kRtcpCompound ||
1959 (rtcp_packet_type & kRtcpReport) ||
1960 (rtcp_packet_type & kRtcpSr) ||
1961 (rtcp_packet_type & kRtcpRr);
1962}
1963
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001964bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
1965 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001966 RTCPReportBlock* report_block,
1967 uint32_t* ntp_secs, uint32_t* ntp_frac) {
1968 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001969 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001970 if (!statistician->GetStatistics(&stats, true))
1971 return false;
1972 report_block->fractionLost = stats.fraction_lost;
1973 report_block->cumulativeLost = stats.cumulative_lost;
1974 report_block->extendedHighSeqNum =
1975 stats.extended_max_sequence_number;
1976 report_block->jitter = stats.jitter;
1977
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001978 // get our NTP as late as possible to avoid a race
1979 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
1980
1981 // Delay since last received report
1982 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001983 if ((feedback_state.last_rr_ntp_secs != 0) ||
1984 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001985 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1986 uint32_t now=*ntp_secs&0x0000FFFF;
1987 now <<=16;
1988 now += (*ntp_frac&0xffff0000)>>16;
1989
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001990 uint32_t receiveTime = feedback_state.last_rr_ntp_secs&0x0000FFFF;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001991 receiveTime <<=16;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001992 receiveTime += (feedback_state.last_rr_ntp_frac&0xffff0000)>>16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001993
1994 delaySinceLastReceivedSR = now-receiveTime;
1995 }
1996 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001997 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001998 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001999}
2000
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002001int32_t
2002RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002003 const size_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002004{
2005 CriticalSectionScoped lock(_criticalSectionTransport);
2006 if(_cbTransport)
2007 {
2008 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
2009 {
2010 return 0;
2011 }
2012 }
2013 return -1;
2014}
2015
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002016int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002017RTCPSender::SetCSRCStatus(const bool include)
2018{
pbos@webrtc.org180e5162014-07-11 15:36:26 +00002019 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +00002020 _includeCSRCs = include;
2021 return 0;
2022}
2023
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002024int32_t
2025RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
2026 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00002027{
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002028 assert(arrLength <= kRtpCsrcSize);
niklase@google.com470e71d2011-07-07 08:21:25 +00002029 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2030
2031 for(int i = 0; i < arrLength;i++)
2032 {
2033 _CSRC[i] = arrOfCSRC[i];
2034 }
2035 _CSRCs = arrLength;
2036 return 0;
2037}
2038
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002039int32_t
2040RTCPSender::SetApplicationSpecificData(const uint8_t subType,
2041 const uint32_t name,
2042 const uint8_t* data,
2043 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002044{
2045 if(length %4 != 0)
2046 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002047 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
niklase@google.com470e71d2011-07-07 08:21:25 +00002048 return -1;
2049 }
2050 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2051
2052 if(_appData)
2053 {
2054 delete [] _appData;
2055 }
2056
2057 _appSend = true;
2058 _appSubType = subType;
2059 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002060 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002061 _appLength = length;
2062 memcpy(_appData, data, length);
2063 return 0;
2064}
2065
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002066int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002067RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2068{
2069 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2070 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2071
2072 _xrSendVoIPMetric = true;
2073 return 0;
2074}
2075
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002076void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
2077 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2078 xrSendReceiverReferenceTimeEnabled_ = enable;
2079}
2080
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00002081bool RTCPSender::RtcpXrReceiverReferenceTime() const {
2082 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2083 return xrSendReceiverReferenceTimeEnabled_;
2084}
2085
niklase@google.com470e71d2011-07-07 08:21:25 +00002086// called under critsect _criticalSectionRTCPSender
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002087int32_t RTCPSender::WriteAllReportBlocksToBuffer(
2088 uint8_t* rtcpbuffer,
2089 int pos,
2090 uint8_t& numberOfReportBlocks,
2091 const uint32_t NTPsec,
2092 const uint32_t NTPfrac) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002093 numberOfReportBlocks = external_report_blocks_.size();
2094 numberOfReportBlocks += internal_report_blocks_.size();
2095 if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002096 LOG(LS_WARNING) << "Can't fit all report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002097 return -1;
2098 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002099 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2100 while (!internal_report_blocks_.empty()) {
2101 delete internal_report_blocks_.begin()->second;
2102 internal_report_blocks_.erase(internal_report_blocks_.begin());
2103 }
2104 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2105 return pos;
2106}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002107
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002108int32_t RTCPSender::WriteReportBlocksToBuffer(
2109 uint8_t* rtcpbuffer,
2110 int32_t position,
2111 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2112 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2113 report_blocks.begin();
2114 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002115 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002116 RTCPReportBlock* reportBlock = it->second;
2117 if (reportBlock) {
2118 // Remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002119 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position, remoteSSRC);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002120 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002121
2122 // fraction lost
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002123 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002124
2125 // cumulative loss
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002126 RtpUtility::AssignUWord24ToBuffer(rtcpbuffer + position,
2127 reportBlock->cumulativeLost);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002128 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002129
2130 // extended highest seq_no, contain the highest sequence number received
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002131 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2132 reportBlock->extendedHighSeqNum);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002133 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002134
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002135 // Jitter
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002136 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2137 reportBlock->jitter);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002138 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002139
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002140 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2141 reportBlock->lastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002142 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002143
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002144 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2145 reportBlock->delaySinceLastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002146 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002147 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002148 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002149 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00002150}
2151
2152// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002153int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002154RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002155 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002156{
2157 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2158
2159 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2160 {
2161 _sendTMMBN = true;
2162 return 0;
2163 }
2164 return -1;
2165}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002166} // namespace webrtc