blob: 3386d9b5fdb07af7296d1886d2821038d38741e2 [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 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000118
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000119 _rembBitrate(0),
120
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000121 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000122 _tmmbr_Send(0),
123 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000124
125 _appSend(false),
126 _appSubType(0),
127 _appName(),
128 _appData(NULL),
129 _appLength(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000130
131 xrSendReceiverReferenceTimeEnabled_(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000132 _xrSendVoIPMetric(false),
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000133 _xrVoIPMetric()
niklase@google.com470e71d2011-07-07 08:21:25 +0000134{
135 memset(_CNAME, 0, sizeof(_CNAME));
136 memset(_lastSendReport, 0, sizeof(_lastSendReport));
137 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
niklase@google.com470e71d2011-07-07 08:21:25 +0000138}
139
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000140RTCPSender::~RTCPSender() {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000141 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000142
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000143 while (!internal_report_blocks_.empty()) {
144 delete internal_report_blocks_.begin()->second;
145 internal_report_blocks_.erase(internal_report_blocks_.begin());
146 }
147 while (!external_report_blocks_.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000148 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000149 external_report_blocks_.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000150 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000151 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000152 }
153 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000154 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000155 _csrcCNAMEs.begin();
156 delete it->second;
157 _csrcCNAMEs.erase(it);
158 }
159 delete _criticalSectionTransport;
160 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000161}
162
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000163int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000164RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
165{
166 CriticalSectionScoped lock(_criticalSectionTransport);
167 _cbTransport = outgoingTransport;
168 return 0;
169}
170
171RTCPMethod
172RTCPSender::Status() const
173{
174 CriticalSectionScoped lock(_criticalSectionRTCPSender);
175 return _method;
176}
177
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000178int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000179RTCPSender::SetRTCPStatus(const RTCPMethod method)
180{
181 CriticalSectionScoped lock(_criticalSectionRTCPSender);
182 if(method != kRtcpOff)
183 {
184 if(_audio)
185 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000186 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000187 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000188 } else
189 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000190 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000191 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000192 }
193 }
194 _method = method;
195 return 0;
196}
197
198bool
199RTCPSender::Sending() const
200{
201 CriticalSectionScoped lock(_criticalSectionRTCPSender);
202 return _sending;
203}
204
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000205int32_t
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000206RTCPSender::SetSendingStatus(const FeedbackState& feedback_state, bool sending)
niklase@google.com470e71d2011-07-07 08:21:25 +0000207{
208 bool sendRTCPBye = false;
209 {
210 CriticalSectionScoped lock(_criticalSectionRTCPSender);
211
212 if(_method != kRtcpOff)
213 {
214 if(sending == false && _sending == true)
215 {
216 // Trigger RTCP bye
217 sendRTCPBye = true;
218 }
219 }
220 _sending = sending;
221 }
222 if(sendRTCPBye)
223 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000224 return SendRTCP(feedback_state, kRtcpBye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000225 }
226 return 0;
227}
228
229bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000230RTCPSender::REMB() const
231{
232 CriticalSectionScoped lock(_criticalSectionRTCPSender);
233 return _REMB;
234}
235
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000236int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000237RTCPSender::SetREMBStatus(const bool enable)
238{
239 CriticalSectionScoped lock(_criticalSectionRTCPSender);
240 _REMB = enable;
241 return 0;
242}
243
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000244int32_t
245RTCPSender::SetREMBData(const uint32_t bitrate,
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000246 const std::vector<uint32_t>& ssrcs)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000247{
248 CriticalSectionScoped lock(_criticalSectionRTCPSender);
249 _rembBitrate = bitrate;
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000250 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000251
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000252 _sendREMB = true;
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000253 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
254 // throttled by the caller.
255 _nextTimeToSendRTCP = _clock->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000256 return 0;
257}
258
259bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000260RTCPSender::TMMBR() const
261{
262 CriticalSectionScoped lock(_criticalSectionRTCPSender);
263 return _TMMBR;
264}
265
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000266int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000267RTCPSender::SetTMMBRStatus(const bool enable)
268{
269 CriticalSectionScoped lock(_criticalSectionRTCPSender);
270 _TMMBR = enable;
271 return 0;
272}
273
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000274bool
275RTCPSender::IJ() const
276{
277 CriticalSectionScoped lock(_criticalSectionRTCPSender);
278 return _IJ;
279}
280
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000281int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000282RTCPSender::SetIJStatus(const bool enable)
283{
284 CriticalSectionScoped lock(_criticalSectionRTCPSender);
285 _IJ = enable;
286 return 0;
287}
288
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000289void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
pbos@webrtc.org180e5162014-07-11 15:36:26 +0000290 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000291 start_timestamp_ = start_timestamp;
292}
293
294void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
295 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000296 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000297 last_rtp_timestamp_ = rtp_timestamp;
298 if (capture_time_ms < 0) {
299 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000300 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000301 } else {
302 last_frame_capture_time_ms_ = capture_time_ms;
303 }
304}
305
niklase@google.com470e71d2011-07-07 08:21:25 +0000306void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000307RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000308{
309 CriticalSectionScoped lock(_criticalSectionRTCPSender);
310
311 if(_SSRC != 0)
312 {
313 // not first SetSSRC, probably due to a collision
314 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000315 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000316 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000317 }
318 _SSRC = ssrc;
319}
320
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000321void RTCPSender::SetRemoteSSRC(uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000322{
323 CriticalSectionScoped lock(_criticalSectionRTCPSender);
324 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000325}
326
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000327int32_t
328RTCPSender::SetCameraDelay(const int32_t delayMS)
329{
330 CriticalSectionScoped lock(_criticalSectionRTCPSender);
331 if(delayMS > 1000 || delayMS < -1000)
332 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000333 LOG(LS_WARNING) << "Delay can't be larger than 1 second: "
334 << delayMS << " ms";
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000335 return -1;
336 }
337 _cameraDelayMS = delayMS;
338 return 0;
339}
340
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000341int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000342 if (!cName)
343 return -1;
344
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000345 CriticalSectionScoped lock(_criticalSectionRTCPSender);
346 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
347 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
348 return 0;
349}
350
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000351int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
352 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000353 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000354 CriticalSectionScoped lock(_criticalSectionRTCPSender);
355 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
356 return -1;
357 }
358 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000359 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
360 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000361 _csrcCNAMEs[SSRC] = ptr;
362 return 0;
363}
364
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000365int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000366 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000367 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000368 _csrcCNAMEs.find(SSRC);
369
370 if (it == _csrcCNAMEs.end()) {
371 return -1;
372 }
373 delete it->second;
374 _csrcCNAMEs.erase(it);
375 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000376}
377
378bool
379RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
380{
381/*
382 For audio we use a fix 5 sec interval
383
384 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000385 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
386 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000387
388
389From RFC 3550
390
391 MAX RTCP BW is 5% if the session BW
392 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000393 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000394
395 The RECOMMENDED value for the reduced minimum in seconds is 360
396 divided by the session bandwidth in kilobits/second. This minimum
397 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
398
399 If the participant has not yet sent an RTCP packet (the variable
400 initial is true), the constant Tmin is set to 2.5 seconds, else it
401 is set to 5 seconds.
402
403 The interval between RTCP packets is varied randomly over the
404 range [0.5,1.5] times the calculated interval to avoid unintended
405 synchronization of all participants
406
407 if we send
408 If the participant is a sender (we_sent true), the constant C is
409 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
410 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
411 number of senders.
412
413 if we receive only
414 If we_sent is not true, the constant C is set
415 to the average RTCP packet size divided by 75% of the RTCP
416 bandwidth. The constant n is set to the number of receivers
417 (members - senders). If the number of senders is greater than
418 25%, senders and receivers are treated together.
419
420 reconsideration NOT required for peer-to-peer
421 "timer reconsideration" is
422 employed. This algorithm implements a simple back-off mechanism
423 which causes users to hold back RTCP packet transmission if the
424 group sizes are increasing.
425
426 n = number of members
427 C = avg_size/(rtcpBW/4)
428
429 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
430
431 4. The calculated interval T is set to a number uniformly distributed
432 between 0.5 and 1.5 times the deterministic calculated interval.
433
434 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
435 for the fact that the timer reconsideration algorithm converges to
436 a value of the RTCP bandwidth below the intended average
437*/
438
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000439 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000440
441 CriticalSectionScoped lock(_criticalSectionRTCPSender);
442
niklase@google.com470e71d2011-07-07 08:21:25 +0000443 if(_method == kRtcpOff)
444 {
445 return false;
446 }
447
niklase@google.com470e71d2011-07-07 08:21:25 +0000448 if(!_audio && sendKeyframeBeforeRTP)
449 {
450 // for video key-frames we want to send the RTCP before the large key-frame
451 // if we have a 100 ms margin
452 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
453 }
454
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000455 if(now >= _nextTimeToSendRTCP)
niklase@google.com470e71d2011-07-07 08:21:25 +0000456 {
457 return true;
458
459 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
460 {
461 // wrap
462 return true;
463 }
464 return false;
465}
466
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000467uint32_t
468RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000469{
470 CriticalSectionScoped lock(_criticalSectionRTCPSender);
471
472 lastRTCPTime = _lastRTCPTime[0];
473 return _lastSendReport[0];
474}
475
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000476uint32_t
477RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000478{
479 CriticalSectionScoped lock(_criticalSectionRTCPSender);
480
481 // This is only saved when we are the sender
482 if((_lastSendReport[0] == 0) || (sendReport == 0))
483 {
484 return 0; // will be ignored
485 } else
486 {
487 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
488 {
489 if( _lastSendReport[i] == sendReport)
490 {
491 return _lastRTCPTime[i];
492 }
493 }
494 }
495 return 0;
496}
497
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000498bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
499 int64_t* time_ms) const {
500 CriticalSectionScoped lock(_criticalSectionRTCPSender);
501
502 if (last_xr_rr_.empty()) {
503 return false;
504 }
505 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
506 if (it == last_xr_rr_.end()) {
507 return false;
508 }
509 *time_ms = it->second;
510 return true;
511}
512
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000513void RTCPSender::GetPacketTypeCounter(
514 RtcpPacketTypeCounter* packet_counter) const {
515 CriticalSectionScoped lock(_criticalSectionRTCPSender);
516 *packet_counter = packet_type_counter_;
517}
518
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000519int32_t RTCPSender::AddExternalReportBlock(
520 uint32_t SSRC,
521 const RTCPReportBlock* reportBlock) {
522 CriticalSectionScoped lock(_criticalSectionRTCPSender);
523 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
524}
525
526int32_t RTCPSender::AddReportBlock(
527 uint32_t SSRC,
528 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
529 const RTCPReportBlock* reportBlock) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000530 assert(reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000531
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000532 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000533 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000534 return -1;
535 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000536 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000537 report_blocks->find(SSRC);
538 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000539 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000540 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000541 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000542 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
543 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000544 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000545 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000546}
547
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000548int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000549 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000550
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000551 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000552 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000553
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000554 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000555 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000556 }
557 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000558 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000559 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000560}
561
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000562int32_t RTCPSender::BuildSR(const FeedbackState& feedback_state,
563 uint8_t* rtcpbuffer,
564 int& pos,
565 uint32_t NTPsec,
566 uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000567{
568 // sanity
569 if(pos + 52 >= IP_PACKET_SIZE)
570 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000571 LOG(LS_WARNING) << "Failed to build Sender Report.";
niklase@google.com470e71d2011-07-07 08:21:25 +0000572 return -2;
573 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000574 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000575
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000576 uint32_t posNumberOfReportBlocks = pos;
577 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000578
579 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000580 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000581
582 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
583 {
584 // shift old
585 _lastSendReport[i+1] = _lastSendReport[i];
586 _lastRTCPTime[i+1] =_lastRTCPTime[i];
587 }
588
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000589 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000590 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000591
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000592 // The timestamp of this RTCP packet should be estimated as the timestamp of
593 // the frame being captured at this moment. We are calculating that
594 // timestamp as the last frame's timestamp + the time since the last frame
595 // was captured.
pbos@webrtc.org180e5162014-07-11 15:36:26 +0000596 RTPtime = start_timestamp_ + last_rtp_timestamp_ +
597 (_clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
598 (feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000599
600 // Add sender data
601 // Save for our length field
602 pos++;
603 pos++;
604
605 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000606 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000607 pos += 4;
608 // NTP
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000609 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000610 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000611 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000612 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000613 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, RTPtime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000614 pos += 4;
615
616 //sender's packet count
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000617 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000618 feedback_state.packets_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000619 pos += 4;
620
621 //sender's octet count
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000622 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000623 feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000624 pos += 4;
625
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000626 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000627 int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
628 numberOfReportBlocks,
629 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000630 if(retVal < 0)
631 {
632 //
633 return retVal ;
634 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000635 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000636 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
637
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000638 uint16_t len = uint16_t((pos/4) -1);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000639 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000640 return 0;
641}
642
643
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000644int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000645 size_t lengthCname = strlen(_CNAME);
646 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000647
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000648 // sanity
649 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000650 LOG(LS_WARNING) << "Failed to build SDEC.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000651 return -2;
652 }
653 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000654
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000655 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000656 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
657 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000658
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000659 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000660 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000661 pos++;
662 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000663
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000664 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000665 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000666 pos += 4;
667
668 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000669 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000670
671 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000672 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000673
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000674 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000675
676 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
677 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000678 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000679
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000680 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000681 // We must have a zero field even if we have an even multiple of 4 bytes
682 if ((pos % 4) == 0) {
683 padding++;
684 rtcpbuffer[pos++]=0;
685 }
686 while ((pos % 4) != 0) {
687 padding++;
688 rtcpbuffer[pos++]=0;
689 }
690 SDESLength += padding;
691
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000692 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000693 _csrcCNAMEs.begin();
694
695 for(; it != _csrcCNAMEs.end(); it++) {
696 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000697 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000698
699 // Add SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000700 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000701 pos += 4;
702
703 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000704 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000705
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000706 size_t length = strlen(cname->name);
707 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000708
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000709 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000710 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000711
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000712 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000713
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000714 pos += length;
715 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000716 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000717
718 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000719 if((pos % 4) == 0){
720 padding++;
721 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000722 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000723 while((pos % 4) != 0){
724 padding++;
725 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000726 }
727 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000728 }
729 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000730 uint16_t buffer_length = (SDESLength / 4) - 1;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000731 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos, buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000732 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000733}
734
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000735int32_t
736RTCPSender::BuildRR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000737 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000738 const uint32_t NTPsec,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000739 const uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000740{
741 // sanity one block
742 if(pos + 32 >= IP_PACKET_SIZE)
743 {
744 return -2;
745 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000746 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000747
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000748 rtcpbuffer[pos++]=(uint8_t)0x80;
749 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000750
751 // Save for our length field
752 pos++;
753 pos++;
754
755 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000756 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000757 pos += 4;
758
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000759 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000760 int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
761 numberOfReportBlocks,
762 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000763 if(retVal < 0)
764 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000765 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000766 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000767 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000768 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
769
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000770 uint16_t len = uint16_t((pos)/4 -1);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000771 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000772 return 0;
773}
774
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000775// From RFC 5450: Transmission Time Offsets in RTP Streams.
776// 0 1 2 3
777// 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
778// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
779// hdr |V=2|P| RC | PT=IJ=195 | length |
780// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
781// | inter-arrival jitter |
782// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
783// . .
784// . .
785// . .
786// | inter-arrival jitter |
787// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
788//
789// If present, this RTCP packet must be placed after a receiver report
790// (inside a compound RTCP packet), and MUST have the same value for RC
791// (reception report count) as the receiver report.
792
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000793int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000794RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000795 uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000796 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000797 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000798{
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000799 if (external_report_blocks_.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000800 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000801 // TODO(andresp): Remove external report blocks since they are not
802 // supported.
803 LOG(LS_ERROR) << "Handling of external report blocks not implemented.";
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000804 return 0;
805 }
806
807 // sanity
808 if(pos + 8 >= IP_PACKET_SIZE)
809 {
810 return -2;
811 }
812 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000813 uint8_t RC = 1;
814 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
815 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000816
817 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000818 rtcpbuffer[pos++]=(uint8_t)0;
819 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000820
821 // Add inter-arrival jitter
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000822 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
823 jitterTransmissionTimeOffset);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000824 pos += 4;
825 return 0;
826}
827
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000828int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000829RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000830{
831 // sanity
832 if(pos + 12 >= IP_PACKET_SIZE)
833 {
834 return -2;
835 }
836 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000837 uint8_t FMT = 1;
838 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
839 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000840
841 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000842 rtcpbuffer[pos++]=(uint8_t)0;
843 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000844
845 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000846 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000847 pos += 4;
848
849 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000850 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000851 pos += 4;
852 return 0;
853}
854
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000855int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000856 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000857 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000858 // sanity
859 if(pos + 20 >= IP_PACKET_SIZE) {
860 return -2;
861 }
862 if (!repeat) {
863 _sequenceNumberFIR++; // do not increase if repetition
864 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000865
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000866 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000867 uint8_t FMT = 4;
868 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
869 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000870
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000871 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000872 rtcpbuffer[pos++] = (uint8_t)0;
873 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000874
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000875 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000876 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000877 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000878
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000879 // RFC 5104 4.3.1.2. Semantics
880 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000881 rtcpbuffer[pos++] = (uint8_t)0;
882 rtcpbuffer[pos++] = (uint8_t)0;
883 rtcpbuffer[pos++] = (uint8_t)0;
884 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000885
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000886 // Additional Feedback Control Information (FCI)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000887 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000888 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000889
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000890 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
891 rtcpbuffer[pos++] = (uint8_t)0;
892 rtcpbuffer[pos++] = (uint8_t)0;
893 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000894 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000895}
896
897/*
898 0 1 2 3
899 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
900 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
901 | First | Number | PictureID |
902 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
903*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000904int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000905RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000906{
907 // sanity
908 if(pos + 16 >= IP_PACKET_SIZE)
909 {
910 return -2;
911 }
912 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000913 uint8_t FMT = 2;
914 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
915 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000916
917 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000918 rtcpbuffer[pos++]=(uint8_t)0;
919 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000920
921 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000922 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000923 pos += 4;
924
925 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000926 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000927 pos += 4;
928
929 // Add first, number & picture ID 6 bits
930 // first = 0, 13 - bits
931 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000932 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000933 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, sliField);
niklase@google.com470e71d2011-07-07 08:21:25 +0000934 pos += 4;
935 return 0;
936}
937
938/*
939 0 1 2 3
940 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
941 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
942 | PB |0| Payload Type| Native RPSI bit string |
943 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
944 | defined per codec ... | Padding (0) |
945 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
946*/
947/*
948* Note: not generic made for VP8
949*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000950int32_t
951RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000952 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000953 const uint64_t pictureID,
954 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +0000955{
956 // sanity
957 if(pos + 24 >= IP_PACKET_SIZE)
958 {
959 return -2;
960 }
961 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000962 uint8_t FMT = 3;
963 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
964 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000965
966 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000967 uint32_t bitsRequired = 7;
968 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000969 while((pictureID>>bitsRequired) > 0)
970 {
971 bitsRequired += 7;
972 bytesRequired++;
973 }
974
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000975 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +0000976 if(bytesRequired > 6)
977 {
978 size = 5;
979 } else if(bytesRequired > 2)
980 {
981 size = 4;
982 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000983 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000984 rtcpbuffer[pos++]=size;
985
986 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000987 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000988 pos += 4;
989
990 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000991 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000992 pos += 4;
993
994 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000995 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000996 if(paddingBytes == 4)
997 {
998 paddingBytes = 0;
999 }
1000 // add padding length in bits
1001 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1002 pos++;
1003
1004 // add payload type
1005 rtcpbuffer[pos] = payloadType;
1006 pos++;
1007
1008 // add picture ID
1009 for(int i = bytesRequired-1; i > 0; i--)
1010 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001011 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001012 pos++;
1013 }
1014 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001015 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001016 pos++;
1017
1018 // add padding
1019 for(int j = 0; j <paddingBytes; j++)
1020 {
1021 rtcpbuffer[pos] = 0;
1022 pos++;
1023 }
1024 return 0;
1025}
1026
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001027int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001028RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001029{
1030 // sanity
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001031 if(pos + 20 + 4 * remb_ssrcs_.size() >= IP_PACKET_SIZE)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001032 {
1033 return -2;
1034 }
1035 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001036 uint8_t FMT = 15;
1037 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1038 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001039
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001040 rtcpbuffer[pos++]=(uint8_t)0;
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001041 rtcpbuffer[pos++]=remb_ssrcs_.size() + 4;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001042
1043 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001044 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001045 pos += 4;
1046
1047 // Remote SSRC must be 0
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001048 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, 0);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001049 pos += 4;
1050
1051 rtcpbuffer[pos++]='R';
1052 rtcpbuffer[pos++]='E';
1053 rtcpbuffer[pos++]='M';
1054 rtcpbuffer[pos++]='B';
1055
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001056 rtcpbuffer[pos++] = remb_ssrcs_.size();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001057 // 6 bit Exp
1058 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001059 uint8_t brExp = 0;
1060 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001061 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001062 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001063 {
1064 brExp = i;
1065 break;
1066 }
1067 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001068 const uint32_t brMantissa = (_rembBitrate >> brExp);
1069 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1070 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1071 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001072
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001073 for (size_t i = 0; i < remb_ssrcs_.size(); i++)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001074 {
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001075 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, remb_ssrcs_[i]);
1076 pos += 4;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001077 }
1078 return 0;
1079}
1080
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001081void
1082RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001083{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001084 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001085 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001086}
1087
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001088int32_t RTCPSender::BuildTMMBR(ModuleRtpRtcpImpl* rtp_rtcp_module,
1089 uint8_t* rtcpbuffer,
1090 int& pos) {
1091 if (rtp_rtcp_module == NULL)
1092 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001093 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1094 // If the sender is an owner of the TMMBN -> send TMMBR
1095 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1096
niklase@google.com470e71d2011-07-07 08:21:25 +00001097 // get current bounding set from RTCP receiver
1098 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001099 // store in candidateSet, allocates one extra slot
1100 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001101
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001102 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1103 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1104 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001105 int32_t lengthOfBoundingSet =
1106 rtp_rtcp_module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001107
1108 if(lengthOfBoundingSet > 0)
1109 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001110 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001111 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001112 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1113 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001114 {
1115 // do not send the same tuple
1116 return 0;
1117 }
1118 }
1119 if(!tmmbrOwner)
1120 {
1121 // use received bounding set as candidate set
1122 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001123 candidateSet->SetEntry(lengthOfBoundingSet,
1124 _tmmbr_Send,
1125 _packetOH_Send,
1126 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001127 int numCandidates = lengthOfBoundingSet+ 1;
1128
1129 // find bounding set
1130 TMMBRSet* boundingSet = NULL;
1131 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1132 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1133 {
1134 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1135 }
1136 if(!tmmbrOwner)
1137 {
1138 // did not enter bounding set, no meaning to send this request
1139 return 0;
1140 }
1141 }
1142 }
1143
1144 if(_tmmbr_Send)
1145 {
1146 // sanity
1147 if(pos + 20 >= IP_PACKET_SIZE)
1148 {
1149 return -2;
1150 }
1151 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001152 uint8_t FMT = 3;
1153 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1154 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001155
1156 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001157 rtcpbuffer[pos++]=(uint8_t)0;
1158 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001159
1160 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001161 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001162 pos += 4;
1163
1164 // RFC 5104 4.2.1.2. Semantics
1165
1166 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001167 rtcpbuffer[pos++]=(uint8_t)0;
1168 rtcpbuffer[pos++]=(uint8_t)0;
1169 rtcpbuffer[pos++]=(uint8_t)0;
1170 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001171
1172 // Additional Feedback Control Information (FCI)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001173 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001174 pos += 4;
1175
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001176 uint32_t bitRate = _tmmbr_Send*1000;
1177 uint32_t mmbrExp = 0;
1178 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001179 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001180 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001181 {
1182 mmbrExp = i;
1183 break;
1184 }
1185 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001186 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001187
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001188 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1189 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1190 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1191 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001192 }
1193 return 0;
1194}
1195
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001196int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001197RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001198{
1199 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1200 if(boundingSet == NULL)
1201 {
1202 return -1;
1203 }
1204 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001205 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001206 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001207 LOG(LS_WARNING) << "Failed to build TMMBN.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001208 return -2;
1209 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001210 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001211 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001212 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1213 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001214
1215 //Add length later
1216 int posLength = pos;
1217 pos++;
1218 pos++;
1219
1220 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001221 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001222 pos += 4;
1223
1224 // RFC 5104 4.2.2.2. Semantics
1225
1226 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001227 rtcpbuffer[pos++]=(uint8_t)0;
1228 rtcpbuffer[pos++]=(uint8_t)0;
1229 rtcpbuffer[pos++]=(uint8_t)0;
1230 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001231
1232 // Additional Feedback Control Information (FCI)
1233 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001234 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001235 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001236 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001237 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001238 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001239 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, tmmbrSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001240 pos += 4;
1241
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001242 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1243 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001244 for(int i=0; i<64; i++)
1245 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001246 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001247 {
1248 mmbrExp = i;
1249 break;
1250 }
1251 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001252 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1253 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001254
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001255 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1256 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1257 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1258 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001259 numBoundingSet++;
1260 }
1261 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001262 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1263 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1264 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001265 return 0;
1266}
1267
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001268int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001269RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001270{
1271 // sanity
1272 if(_appData == NULL)
1273 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001274 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001275 return -1;
1276 }
1277 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1278 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001279 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001280 return -2;
1281 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001282 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001283
1284 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001285 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001286
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001287 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1288 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1289 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001290
1291 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001292 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001293 pos += 4;
1294
1295 // Add our application name
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001296 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _appName);
niklase@google.com470e71d2011-07-07 08:21:25 +00001297 pos += 4;
1298
1299 // Add the data
1300 memcpy(rtcpbuffer +pos, _appData,_appLength);
1301 pos += _appLength;
1302 return 0;
1303}
1304
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001305int32_t
1306RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001307 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001308 const int32_t nackSize,
1309 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001310 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001311{
1312 // sanity
1313 if(pos + 16 >= IP_PACKET_SIZE)
1314 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001315 LOG(LS_WARNING) << "Failed to build NACK.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001316 return -2;
1317 }
1318
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001319 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001320 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001321 uint8_t FMT = 1;
1322 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1323 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001324
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001325 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001326 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001327 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001328
1329 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001330 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001331 pos += 4;
1332
1333 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001334 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001335 pos += 4;
1336
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001337 // Build NACK bitmasks and write them to the RTCP message.
1338 // The nack list should be sorted and not contain duplicates if one
1339 // wants to build the smallest rtcp nack packet.
1340 int numOfNackFields = 0;
1341 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1342 (IP_PACKET_SIZE - pos) / 4);
1343 int i = 0;
1344 while (i < nackSize && numOfNackFields < maxNackFields) {
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001345 uint16_t nack = nackList[i++];
1346 uint16_t bitmask = 0;
1347 while (i < nackSize) {
1348 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1349 if (shift >= 0 && shift <= 15) {
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001350 bitmask |= (1 << shift);
1351 ++i;
1352 } else {
1353 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001354 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001355 }
1356 // Write the sequence number and the bitmask to the packet.
1357 assert(pos + 4 < IP_PACKET_SIZE);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001358 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001359 pos += 2;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001360 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001361 pos += 2;
1362 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001363 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001364 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001365
1366 if (i != nackSize) {
1367 LOG(LS_WARNING) << "Nack list too large for one packet.";
1368 }
1369
1370 // Report stats.
1371 NACKStringBuilder stringBuilder;
1372 for (int idx = 0; idx < i; ++idx) {
1373 stringBuilder.PushNACK(nackList[idx]);
1374 nack_stats_.ReportRequest(nackList[idx]);
1375 }
edjee@google.com79b02892013-04-04 19:43:34 +00001376 *nackString = stringBuilder.GetResult();
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001377 packet_type_counter_.nack_requests = nack_stats_.requests();
1378 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
niklase@google.com470e71d2011-07-07 08:21:25 +00001379 return 0;
1380}
1381
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001382int32_t RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos) {
1383 // sanity
1384 if (pos + 8 >= IP_PACKET_SIZE) {
1385 return -2;
1386 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001387
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001388 // Add a bye packet
1389 // Number of SSRC + CSRCs.
1390 rtcpbuffer[pos++] = (uint8_t)0x80 + 1 + csrcs_.size();
1391 rtcpbuffer[pos++] = (uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001392
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001393 // length
1394 rtcpbuffer[pos++] = (uint8_t)0;
1395 rtcpbuffer[pos++] = (uint8_t)(1 + csrcs_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +00001396
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001397 // Add our own SSRC
1398 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
1399 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001400
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001401 // add CSRCs
1402 for (size_t i = 0; i < csrcs_.size(); i++) {
1403 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, csrcs_[i]);
1404 pos += 4;
1405 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001406
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001407 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001408}
1409
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001410int32_t RTCPSender::BuildReceiverReferenceTime(uint8_t* buffer,
1411 int& pos,
1412 uint32_t ntp_sec,
1413 uint32_t ntp_frac) {
1414 const int kRrTimeBlockLength = 20;
1415 if (pos + kRrTimeBlockLength >= IP_PACKET_SIZE) {
1416 return -2;
1417 }
1418
1419 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) {
1420 last_xr_rr_.erase(last_xr_rr_.begin());
1421 }
1422 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
1423 RTCPUtility::MidNtp(ntp_sec, ntp_frac),
1424 Clock::NtpToMs(ntp_sec, ntp_frac)));
1425
1426 // Add XR header.
1427 buffer[pos++] = 0x80;
1428 buffer[pos++] = 207;
1429 buffer[pos++] = 0; // XR packet length.
1430 buffer[pos++] = 4; // XR packet length.
1431
1432 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001433 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001434 pos += 4;
1435
1436 // 0 1 2 3
1437 // 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
1438 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1439 // | BT=4 | reserved | block length = 2 |
1440 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1441 // | NTP timestamp, most significant word |
1442 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1443 // | NTP timestamp, least significant word |
1444 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1445
1446 // Add Receiver Reference Time Report block.
1447 buffer[pos++] = 4; // BT.
1448 buffer[pos++] = 0; // Reserved.
1449 buffer[pos++] = 0; // Block length.
1450 buffer[pos++] = 2; // Block length.
1451
1452 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001453 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_sec);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001454 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001455 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001456 pos += 4;
1457
1458 return 0;
1459}
1460
1461int32_t RTCPSender::BuildDlrr(uint8_t* buffer,
1462 int& pos,
1463 const RtcpReceiveTimeInfo& info) {
1464 const int kDlrrBlockLength = 24;
1465 if (pos + kDlrrBlockLength >= IP_PACKET_SIZE) {
1466 return -2;
1467 }
1468
1469 // Add XR header.
1470 buffer[pos++] = 0x80;
1471 buffer[pos++] = 207;
1472 buffer[pos++] = 0; // XR packet length.
1473 buffer[pos++] = 5; // XR packet length.
1474
1475 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001476 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001477 pos += 4;
1478
1479 // 0 1 2 3
1480 // 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
1481 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1482 // | BT=5 | reserved | block length |
1483 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1484 // | SSRC_1 (SSRC of first receiver) | sub-
1485 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1486 // | last RR (LRR) | 1
1487 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1488 // | delay since last RR (DLRR) |
1489 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1490 // | SSRC_2 (SSRC of second receiver) | sub-
1491 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1492 // : ... : 2
1493
1494 // Add DLRR sub block.
1495 buffer[pos++] = 5; // BT.
1496 buffer[pos++] = 0; // Reserved.
1497 buffer[pos++] = 0; // Block length.
1498 buffer[pos++] = 3; // Block length.
1499
1500 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001501 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.sourceSSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001502 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001503 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.lastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001504 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001505 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.delaySinceLastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001506 pos += 4;
1507
1508 return 0;
1509}
1510
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001511int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001512RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001513{
1514 // sanity
1515 if(pos + 44 >= IP_PACKET_SIZE)
1516 {
1517 return -2;
1518 }
1519
1520 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001521 rtcpbuffer[pos++]=(uint8_t)0x80;
1522 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001523
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001524 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001525
1526 // handle length later on
1527 pos++;
1528 pos++;
1529
1530 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001531 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001532 pos += 4;
1533
1534 // Add a VoIP metrics block
1535 rtcpbuffer[pos++]=7;
1536 rtcpbuffer[pos++]=0;
1537 rtcpbuffer[pos++]=0;
1538 rtcpbuffer[pos++]=8;
1539
1540 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001541 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001542 pos += 4;
1543
1544 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1545 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1546 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1547 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1548
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001549 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1550 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1551 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1552 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001553
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001554 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1555 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1556 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1557 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001558
1559 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1560 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1561 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1562 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1563
1564 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1565 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1566 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1567 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1568
1569 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1570 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001571 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1572 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001573
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001574 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1575 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1576 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1577 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001578
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001579 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1580 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001581 return 0;
1582}
1583
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001584int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
1585 uint32_t packetTypeFlags,
1586 int32_t nackSize,
1587 const uint16_t* nackList,
1588 bool repeat,
1589 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001590 {
1591 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1592 if(_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001593 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001594 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001595 return -1;
1596 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001597 }
1598 uint8_t rtcp_buffer[IP_PACKET_SIZE];
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001599 int rtcp_length = PrepareRTCP(feedback_state,
1600 packetTypeFlags,
1601 nackSize,
1602 nackList,
1603 repeat,
1604 pictureID,
1605 rtcp_buffer,
1606 IP_PACKET_SIZE);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001607 if (rtcp_length < 0) {
1608 return -1;
1609 }
1610 // Sanity don't send empty packets.
1611 if (rtcp_length == 0)
1612 {
1613 return -1;
1614 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001615 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001616}
1617
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001618int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
1619 uint32_t packetTypeFlags,
1620 int32_t nackSize,
1621 const uint16_t* nackList,
1622 bool repeat,
1623 uint64_t pictureID,
1624 uint8_t* rtcp_buffer,
1625 int buffer_size) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001626 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1627 // Collect the received information.
1628 uint32_t NTPsec = 0;
1629 uint32_t NTPfrac = 0;
1630 uint32_t jitterTransmissionOffset = 0;
1631 int position = 0;
1632
1633 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1634
1635 if(_TMMBR ) // Attach TMMBR to send and receive reports.
1636 {
1637 rtcpPacketTypeFlags |= kRtcpTmmbr;
1638 }
1639 if(_appSend)
1640 {
1641 rtcpPacketTypeFlags |= kRtcpApp;
1642 _appSend = false;
1643 }
1644 if(_REMB && _sendREMB)
1645 {
1646 // Always attach REMB to SR if that is configured. Note that REMB is
1647 // only sent on one of the RTP modules in the REMB group.
1648 rtcpPacketTypeFlags |= kRtcpRemb;
1649 }
1650 if(_xrSendVoIPMetric)
1651 {
1652 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1653 _xrSendVoIPMetric = false;
1654 }
1655 if(_sendTMMBN) // Set when having received a TMMBR.
1656 {
1657 rtcpPacketTypeFlags |= kRtcpTmmbn;
1658 _sendTMMBN = false;
1659 }
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001660 if (rtcpPacketTypeFlags & kRtcpReport)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001661 {
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001662 if (xrSendReceiverReferenceTimeEnabled_ && !_sending)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001663 {
1664 rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
1665 }
1666 if (feedback_state.has_last_xr_rr)
1667 {
1668 rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
1669 }
1670 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001671 if(_method == kRtcpCompound)
1672 {
1673 if(_sending)
1674 {
1675 rtcpPacketTypeFlags |= kRtcpSr;
1676 } else
1677 {
1678 rtcpPacketTypeFlags |= kRtcpRr;
1679 }
1680 } else if(_method == kRtcpNonCompound)
1681 {
1682 if(rtcpPacketTypeFlags & kRtcpReport)
1683 {
1684 if(_sending)
1685 {
1686 rtcpPacketTypeFlags |= kRtcpSr;
1687 } else
1688 {
1689 rtcpPacketTypeFlags |= kRtcpRr;
1690 }
1691 }
1692 }
1693 if( rtcpPacketTypeFlags & kRtcpRr ||
1694 rtcpPacketTypeFlags & kRtcpSr)
1695 {
1696 // generate next time to send a RTCP report
1697 // seeded from RTP constructor
1698 int32_t random = rand() % 1000;
1699 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1700
1701 if(_audio)
1702 {
1703 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1704 (RTCP_INTERVAL_AUDIO_MS*random/1000);
1705 }else
1706 {
1707 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1708 if(_sending)
1709 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001710 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1711 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1712 if (send_bitrate_kbit != 0)
1713 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001714 }
1715 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1716 {
1717 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1718 }
1719 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1720 }
1721 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1722 }
1723
1724 // If the data does not fit in the packet we fill it as much as possible.
1725 int32_t buildVal = 0;
1726
1727 // We need to send our NTP even if we haven't received any reports.
1728 _clock->CurrentNtp(NTPsec, NTPfrac);
1729 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1730 StatisticianMap statisticians =
1731 receive_statistics_->GetActiveStatisticians();
1732 if (!statisticians.empty()) {
1733 StatisticianMap::const_iterator it;
1734 int i;
1735 for (it = statisticians.begin(), i = 0; it != statisticians.end();
1736 ++it, ++i) {
1737 RTCPReportBlock report_block;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001738 if (PrepareReport(
1739 feedback_state, it->second, &report_block, &NTPsec, &NTPfrac))
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001740 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1741 }
1742 if (_IJ && !statisticians.empty()) {
1743 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1744 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001745 }
1746 }
1747
1748 if(rtcpPacketTypeFlags & kRtcpSr)
1749 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001750 buildVal = BuildSR(feedback_state, rtcp_buffer, position, NTPsec, NTPfrac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001751 if (buildVal == -1) {
1752 return -1;
1753 } else if (buildVal == -2) {
1754 return position;
1755 }
1756 buildVal = BuildSDEC(rtcp_buffer, position);
1757 if (buildVal == -1) {
1758 return -1;
1759 } else if (buildVal == -2) {
1760 return position;
1761 }
1762 }else if(rtcpPacketTypeFlags & kRtcpRr)
1763 {
1764 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1765 if (buildVal == -1) {
1766 return -1;
1767 } else if (buildVal == -2) {
1768 return position;
1769 }
1770 // only of set
1771 if(_CNAME[0] != 0)
1772 {
1773 buildVal = BuildSDEC(rtcp_buffer, position);
1774 if (buildVal == -1) {
1775 return -1;
1776 }
1777 }
1778 }
1779 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1780 {
1781 // If present, this RTCP packet must be placed after a
1782 // receiver report.
1783 buildVal = BuildExtendedJitterReport(rtcp_buffer,
1784 position,
1785 jitterTransmissionOffset);
1786 if (buildVal == -1) {
1787 return -1;
1788 } else if (buildVal == -2) {
1789 return position;
1790 }
1791 }
1792 if(rtcpPacketTypeFlags & kRtcpPli)
1793 {
1794 buildVal = BuildPLI(rtcp_buffer, position);
1795 if (buildVal == -1) {
1796 return -1;
1797 } else if (buildVal == -2) {
1798 return position;
1799 }
1800 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001801 ++packet_type_counter_.pli_packets;
1802 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC,
1803 packet_type_counter_.pli_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001804 }
1805 if(rtcpPacketTypeFlags & kRtcpFir)
1806 {
1807 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1808 if (buildVal == -1) {
1809 return -1;
1810 } else if (buildVal == -2) {
1811 return position;
1812 }
1813 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001814 ++packet_type_counter_.fir_packets;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001815 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001816 packet_type_counter_.fir_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001817 }
1818 if(rtcpPacketTypeFlags & kRtcpSli)
1819 {
1820 buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1821 if (buildVal == -1) {
1822 return -1;
1823 } else if (buildVal == -2) {
1824 return position;
1825 }
1826 }
1827 if(rtcpPacketTypeFlags & kRtcpRpsi)
1828 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001829 const int8_t payloadType = feedback_state.send_payload_type;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001830 if (payloadType == -1) {
1831 return -1;
1832 }
1833 buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1834 (uint8_t)payloadType);
1835 if (buildVal == -1) {
1836 return -1;
1837 } else if (buildVal == -2) {
1838 return position;
1839 }
1840 }
1841 if(rtcpPacketTypeFlags & kRtcpRemb)
1842 {
1843 buildVal = BuildREMB(rtcp_buffer, position);
1844 if (buildVal == -1) {
1845 return -1;
1846 } else if (buildVal == -2) {
1847 return position;
1848 }
1849 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1850 }
1851 if(rtcpPacketTypeFlags & kRtcpBye)
1852 {
1853 buildVal = BuildBYE(rtcp_buffer, position);
1854 if (buildVal == -1) {
1855 return -1;
1856 } else if (buildVal == -2) {
1857 return position;
1858 }
1859 }
1860 if(rtcpPacketTypeFlags & kRtcpApp)
1861 {
1862 buildVal = BuildAPP(rtcp_buffer, position);
1863 if (buildVal == -1) {
1864 return -1;
1865 } else if (buildVal == -2) {
1866 return position;
1867 }
1868 }
1869 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1870 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001871 buildVal = BuildTMMBR(feedback_state.module, rtcp_buffer, position);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001872 if (buildVal == -1) {
1873 return -1;
1874 } else if (buildVal == -2) {
1875 return position;
1876 }
1877 }
1878 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1879 {
1880 buildVal = BuildTMMBN(rtcp_buffer, position);
1881 if (buildVal == -1) {
1882 return -1;
1883 } else if (buildVal == -2) {
1884 return position;
1885 }
1886 }
1887 if(rtcpPacketTypeFlags & kRtcpNack)
1888 {
1889 std::string nackString;
1890 buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
1891 &nackString);
1892 if (buildVal == -1) {
1893 return -1;
1894 } else if (buildVal == -2) {
1895 return position;
1896 }
1897 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
1898 "nacks", TRACE_STR_COPY(nackString.c_str()));
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001899 ++packet_type_counter_.nack_packets;
1900 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC,
1901 packet_type_counter_.nack_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001902 }
1903 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1904 {
1905 buildVal = BuildVoIPMetric(rtcp_buffer, position);
1906 if (buildVal == -1) {
1907 return -1;
1908 } else if (buildVal == -2) {
1909 return position;
1910 }
1911 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001912 if (rtcpPacketTypeFlags & kRtcpXrReceiverReferenceTime)
1913 {
1914 buildVal = BuildReceiverReferenceTime(rtcp_buffer,
1915 position,
1916 NTPsec,
1917 NTPfrac);
1918 if (buildVal == -1) {
1919 return -1;
1920 } else if (buildVal == -2) {
1921 return position;
1922 }
1923 }
1924 if (rtcpPacketTypeFlags & kRtcpXrDlrrReportBlock)
1925 {
1926 buildVal = BuildDlrr(rtcp_buffer, position, feedback_state.last_xr_rr);
1927 if (buildVal == -1) {
1928 return -1;
1929 } else if (buildVal == -2) {
1930 return position;
1931 }
1932 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001933 return position;
1934}
1935
1936bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
1937 return Status() == kRtcpCompound ||
1938 (rtcp_packet_type & kRtcpReport) ||
1939 (rtcp_packet_type & kRtcpSr) ||
1940 (rtcp_packet_type & kRtcpRr);
1941}
1942
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001943bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
1944 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001945 RTCPReportBlock* report_block,
1946 uint32_t* ntp_secs, uint32_t* ntp_frac) {
1947 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001948 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001949 if (!statistician->GetStatistics(&stats, true))
1950 return false;
1951 report_block->fractionLost = stats.fraction_lost;
1952 report_block->cumulativeLost = stats.cumulative_lost;
1953 report_block->extendedHighSeqNum =
1954 stats.extended_max_sequence_number;
1955 report_block->jitter = stats.jitter;
1956
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001957 // get our NTP as late as possible to avoid a race
1958 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
1959
1960 // Delay since last received report
1961 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001962 if ((feedback_state.last_rr_ntp_secs != 0) ||
1963 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001964 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1965 uint32_t now=*ntp_secs&0x0000FFFF;
1966 now <<=16;
1967 now += (*ntp_frac&0xffff0000)>>16;
1968
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001969 uint32_t receiveTime = feedback_state.last_rr_ntp_secs&0x0000FFFF;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001970 receiveTime <<=16;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001971 receiveTime += (feedback_state.last_rr_ntp_frac&0xffff0000)>>16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001972
1973 delaySinceLastReceivedSR = now-receiveTime;
1974 }
1975 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001976 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001977 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001978}
1979
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001980int32_t
1981RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001982 const size_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00001983{
1984 CriticalSectionScoped lock(_criticalSectionTransport);
1985 if(_cbTransport)
1986 {
1987 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1988 {
1989 return 0;
1990 }
1991 }
1992 return -1;
1993}
1994
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001995void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1996 assert(csrcs.size() <= kRtpCsrcSize);
1997 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1998 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001999}
2000
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002001int32_t
2002RTCPSender::SetApplicationSpecificData(const uint8_t subType,
2003 const uint32_t name,
2004 const uint8_t* data,
2005 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002006{
2007 if(length %4 != 0)
2008 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002009 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
niklase@google.com470e71d2011-07-07 08:21:25 +00002010 return -1;
2011 }
2012 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2013
2014 if(_appData)
2015 {
2016 delete [] _appData;
2017 }
2018
2019 _appSend = true;
2020 _appSubType = subType;
2021 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002022 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002023 _appLength = length;
2024 memcpy(_appData, data, length);
2025 return 0;
2026}
2027
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002028int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002029RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2030{
2031 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2032 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2033
2034 _xrSendVoIPMetric = true;
2035 return 0;
2036}
2037
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002038void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
2039 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2040 xrSendReceiverReferenceTimeEnabled_ = enable;
2041}
2042
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00002043bool RTCPSender::RtcpXrReceiverReferenceTime() const {
2044 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2045 return xrSendReceiverReferenceTimeEnabled_;
2046}
2047
niklase@google.com470e71d2011-07-07 08:21:25 +00002048// called under critsect _criticalSectionRTCPSender
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002049int32_t RTCPSender::WriteAllReportBlocksToBuffer(
2050 uint8_t* rtcpbuffer,
2051 int pos,
2052 uint8_t& numberOfReportBlocks,
2053 const uint32_t NTPsec,
2054 const uint32_t NTPfrac) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002055 numberOfReportBlocks = external_report_blocks_.size();
2056 numberOfReportBlocks += internal_report_blocks_.size();
2057 if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002058 LOG(LS_WARNING) << "Can't fit all report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002059 return -1;
2060 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002061 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2062 while (!internal_report_blocks_.empty()) {
2063 delete internal_report_blocks_.begin()->second;
2064 internal_report_blocks_.erase(internal_report_blocks_.begin());
2065 }
2066 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2067 return pos;
2068}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002069
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002070int32_t RTCPSender::WriteReportBlocksToBuffer(
2071 uint8_t* rtcpbuffer,
2072 int32_t position,
2073 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2074 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2075 report_blocks.begin();
2076 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002077 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002078 RTCPReportBlock* reportBlock = it->second;
2079 if (reportBlock) {
2080 // Remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002081 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position, remoteSSRC);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002082 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002083
2084 // fraction lost
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002085 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002086
2087 // cumulative loss
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002088 RtpUtility::AssignUWord24ToBuffer(rtcpbuffer + position,
2089 reportBlock->cumulativeLost);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002090 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002091
2092 // extended highest seq_no, contain the highest sequence number received
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002093 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2094 reportBlock->extendedHighSeqNum);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002095 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002096
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002097 // Jitter
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002098 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2099 reportBlock->jitter);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002100 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002101
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002102 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2103 reportBlock->lastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002104 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002105
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002106 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2107 reportBlock->delaySinceLastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002108 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002109 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002110 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002111 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00002112}
2113
2114// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002115int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002116RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002117 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002118{
2119 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2120
2121 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2122 {
2123 _sendTMMBN = true;
2124 return 0;
2125 }
2126 return -1;
2127}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002128} // namespace webrtc