blob: f3c33bf6d742df7ea0e4fef31b257f7f9da1844a [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"
22#include "webrtc/system_wrappers/interface/trace.h"
23#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000024
niklase@google.com470e71d2011-07-07 08:21:25 +000025namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000026
27using RTCPUtility::RTCPCnameInformation;
28
edjee@google.com79b02892013-04-04 19:43:34 +000029NACKStringBuilder::NACKStringBuilder() :
30 _stream(""), _count(0), _consecutive(false)
31{
32 // Empty.
33}
34
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000035NACKStringBuilder::~NACKStringBuilder() {}
36
pbos@webrtc.org2f446732013-04-08 11:08:41 +000037void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000038{
39 if (_count == 0)
40 {
41 _stream << nack;
42 } else if (nack == _prevNack + 1)
43 {
44 _consecutive = true;
45 } else
46 {
47 if (_consecutive)
48 {
49 _stream << "-" << _prevNack;
50 _consecutive = false;
51 }
52 _stream << "," << nack;
53 }
54 _count++;
55 _prevNack = nack;
56}
57
58std::string NACKStringBuilder::GetResult()
59{
60 if (_consecutive)
61 {
62 _stream << "-" << _prevNack;
63 _consecutive = false;
64 }
65 return _stream.str();
66}
67
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000068RTCPSender::FeedbackState::FeedbackState(ModuleRtpRtcpImpl* module)
69 : send_payload_type(module->SendPayloadType()),
70 frequency_hz(module->CurrentSendFrequencyHz()),
71 packet_count_sent(module->PacketCountSent()),
72 byte_count_sent(module->ByteCountSent()),
73 module(module) {
74 uint32_t last_ntp_secs = 0, last_ntp_frac = 0, last_remote_sr = 0;
75 module->LastReceivedNTP(last_ntp_secs, last_ntp_frac, last_remote_sr);
76 last_rr_ntp_secs = last_ntp_secs;
77 last_rr_ntp_frac = last_ntp_frac;
78 remote_sr = last_remote_sr;
79
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000080 has_last_xr_rr = module->LastReceivedXrReferenceTimeInfo(&last_xr_rr);
81
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000082 uint32_t send_bitrate = 0, tmp;
83 module->BitrateSent(&send_bitrate, &tmp, &tmp, &tmp);
84 this->send_bitrate = send_bitrate;
85}
86
87RTCPSender::FeedbackState::FeedbackState()
88 : send_payload_type(0),
89 frequency_hz(0),
90 packet_count_sent(0),
91 byte_count_sent(0),
92 send_bitrate(0),
93 last_rr_ntp_secs(0),
94 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000095 remote_sr(0),
96 has_last_xr_rr(false) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000097
pbos@webrtc.org2f446732013-04-08 11:08:41 +000098RTCPSender::RTCPSender(const int32_t id,
niklase@google.com470e71d2011-07-07 08:21:25 +000099 const bool audio,
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000100 Clock* clock,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000101 ReceiveStatistics* receive_statistics) :
niklase@google.com470e71d2011-07-07 08:21:25 +0000102 _id(id),
103 _audio(audio),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000104 _clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +0000105 _method(kRtcpOff),
henrike@webrtc.org65573f22011-12-13 19:17:27 +0000106 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +0000107 _cbTransport(NULL),
108
henrike@webrtc.org65573f22011-12-13 19:17:27 +0000109 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +0000110 _usingNack(false),
111 _sending(false),
112 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000113 _REMB(false),
114 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000115 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000116 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000117 _nextTimeToSendRTCP(0),
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000118 start_timestamp_(0),
119 last_rtp_timestamp_(0),
120 last_frame_capture_time_ms_(-1),
niklase@google.com470e71d2011-07-07 08:21:25 +0000121 _SSRC(0),
122 _remoteSSRC(0),
123 _CNAME(),
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000124 receive_statistics_(receive_statistics),
125 internal_report_blocks_(),
126 external_report_blocks_(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000127 _csrcCNAMEs(),
128
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000129 _cameraDelayMS(0),
130
niklase@google.com470e71d2011-07-07 08:21:25 +0000131 _lastSendReport(),
132 _lastRTCPTime(),
133
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000134 last_xr_rr_(),
135
niklase@google.com470e71d2011-07-07 08:21:25 +0000136 _CSRCs(0),
137 _CSRC(),
138 _includeCSRCs(true),
139
140 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000141
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000142 _lengthRembSSRC(0),
143 _sizeRembSSRC(0),
144 _rembSSRC(NULL),
145 _rembBitrate(0),
146
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000147 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000148 _tmmbr_Send(0),
149 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000150
151 _appSend(false),
152 _appSubType(0),
153 _appName(),
154 _appData(NULL),
155 _appLength(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000156
157 xrSendReceiverReferenceTimeEnabled_(false),
niklase@google.com470e71d2011-07-07 08:21:25 +0000158 _xrSendVoIPMetric(false),
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000159 _xrVoIPMetric()
niklase@google.com470e71d2011-07-07 08:21:25 +0000160{
161 memset(_CNAME, 0, sizeof(_CNAME));
162 memset(_lastSendReport, 0, sizeof(_lastSendReport));
163 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
164
165 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
166}
167
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000168RTCPSender::~RTCPSender() {
169 delete [] _rembSSRC;
170 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000171
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000172 while (!internal_report_blocks_.empty()) {
173 delete internal_report_blocks_.begin()->second;
174 internal_report_blocks_.erase(internal_report_blocks_.begin());
175 }
176 while (!external_report_blocks_.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000177 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000178 external_report_blocks_.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000179 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000180 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000181 }
182 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000183 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000184 _csrcCNAMEs.begin();
185 delete it->second;
186 _csrcCNAMEs.erase(it);
187 }
188 delete _criticalSectionTransport;
189 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000190
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000191 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000192}
193
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000194int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000195RTCPSender::Init()
196{
197 CriticalSectionScoped lock(_criticalSectionRTCPSender);
198
199 _method = kRtcpOff;
200 _cbTransport = NULL;
201 _usingNack = false;
202 _sending = false;
203 _sendTMMBN = false;
204 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000205 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000206 _REMB = false;
207 _sendREMB = false;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000208 last_rtp_timestamp_ = 0;
209 last_frame_capture_time_ms_ = -1;
210 start_timestamp_ = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000211 _SSRC = 0;
212 _remoteSSRC = 0;
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000213 _cameraDelayMS = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000214 _sequenceNumberFIR = 0;
215 _tmmbr_Send = 0;
216 _packetOH_Send = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000217 _nextTimeToSendRTCP = 0;
218 _CSRCs = 0;
219 _appSend = false;
220 _appSubType = 0;
221
222 if(_appData)
223 {
224 delete [] _appData;
225 _appData = NULL;
226 }
227 _appLength = 0;
228
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000229 xrSendReceiverReferenceTimeEnabled_ = false;
230
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 _xrSendVoIPMetric = false;
232
233 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
234 memset(_CNAME, 0, sizeof(_CNAME));
235 memset(_lastSendReport, 0, sizeof(_lastSendReport));
236 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000237 last_xr_rr_.clear();
edjee@google.com79b02892013-04-04 19:43:34 +0000238
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000239 memset(&packet_type_counter_, 0, sizeof(packet_type_counter_));
niklase@google.com470e71d2011-07-07 08:21:25 +0000240 return 0;
241}
242
243void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000244RTCPSender::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +0000245{
246 _id = id;
247}
248
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000249int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000250RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
251{
252 CriticalSectionScoped lock(_criticalSectionTransport);
253 _cbTransport = outgoingTransport;
254 return 0;
255}
256
257RTCPMethod
258RTCPSender::Status() const
259{
260 CriticalSectionScoped lock(_criticalSectionRTCPSender);
261 return _method;
262}
263
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000264int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000265RTCPSender::SetRTCPStatus(const RTCPMethod method)
266{
267 CriticalSectionScoped lock(_criticalSectionRTCPSender);
268 if(method != kRtcpOff)
269 {
270 if(_audio)
271 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000272 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000273 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000274 } else
275 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000276 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000277 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000278 }
279 }
280 _method = method;
281 return 0;
282}
283
284bool
285RTCPSender::Sending() const
286{
287 CriticalSectionScoped lock(_criticalSectionRTCPSender);
288 return _sending;
289}
290
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000291int32_t
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000292RTCPSender::SetSendingStatus(const FeedbackState& feedback_state, bool sending)
niklase@google.com470e71d2011-07-07 08:21:25 +0000293{
294 bool sendRTCPBye = false;
295 {
296 CriticalSectionScoped lock(_criticalSectionRTCPSender);
297
298 if(_method != kRtcpOff)
299 {
300 if(sending == false && _sending == true)
301 {
302 // Trigger RTCP bye
303 sendRTCPBye = true;
304 }
305 }
306 _sending = sending;
307 }
308 if(sendRTCPBye)
309 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000310 return SendRTCP(feedback_state, kRtcpBye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000311 }
312 return 0;
313}
314
315bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000316RTCPSender::REMB() const
317{
318 CriticalSectionScoped lock(_criticalSectionRTCPSender);
319 return _REMB;
320}
321
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000322int32_t
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000323RTCPSender::SetREMBStatus(const bool enable)
324{
325 CriticalSectionScoped lock(_criticalSectionRTCPSender);
326 _REMB = enable;
327 return 0;
328}
329
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000330int32_t
331RTCPSender::SetREMBData(const uint32_t bitrate,
332 const uint8_t numberOfSSRC,
333 const uint32_t* SSRC)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000334{
335 CriticalSectionScoped lock(_criticalSectionRTCPSender);
336 _rembBitrate = bitrate;
337
338 if(_sizeRembSSRC < numberOfSSRC)
339 {
340 delete [] _rembSSRC;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000341 _rembSSRC = new uint32_t[numberOfSSRC];
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000342 _sizeRembSSRC = numberOfSSRC;
343 }
344
345 _lengthRembSSRC = numberOfSSRC;
346 for (int i = 0; i < numberOfSSRC; i++)
347 {
348 _rembSSRC[i] = SSRC[i];
349 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000350 _sendREMB = true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000351 return 0;
352}
353
354bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000355RTCPSender::TMMBR() const
356{
357 CriticalSectionScoped lock(_criticalSectionRTCPSender);
358 return _TMMBR;
359}
360
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000361int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000362RTCPSender::SetTMMBRStatus(const bool enable)
363{
364 CriticalSectionScoped lock(_criticalSectionRTCPSender);
365 _TMMBR = enable;
366 return 0;
367}
368
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000369bool
370RTCPSender::IJ() const
371{
372 CriticalSectionScoped lock(_criticalSectionRTCPSender);
373 return _IJ;
374}
375
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000376int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000377RTCPSender::SetIJStatus(const bool enable)
378{
379 CriticalSectionScoped lock(_criticalSectionRTCPSender);
380 _IJ = enable;
381 return 0;
382}
383
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000384void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
385 start_timestamp_ = start_timestamp;
386}
387
388void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
389 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000390 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000391 last_rtp_timestamp_ = rtp_timestamp;
392 if (capture_time_ms < 0) {
393 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000394 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000395 } else {
396 last_frame_capture_time_ms_ = capture_time_ms;
397 }
398}
399
niklase@google.com470e71d2011-07-07 08:21:25 +0000400void
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000401RTCPSender::SetSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000402{
403 CriticalSectionScoped lock(_criticalSectionRTCPSender);
404
405 if(_SSRC != 0)
406 {
407 // not first SetSSRC, probably due to a collision
408 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000409 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000410 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000411 }
412 _SSRC = ssrc;
413}
414
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000415void RTCPSender::SetRemoteSSRC(uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000416{
417 CriticalSectionScoped lock(_criticalSectionRTCPSender);
418 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000419}
420
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000421int32_t
422RTCPSender::SetCameraDelay(const int32_t delayMS)
423{
424 CriticalSectionScoped lock(_criticalSectionRTCPSender);
425 if(delayMS > 1000 || delayMS < -1000)
426 {
427 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
428 return -1;
429 }
430 _cameraDelayMS = delayMS;
431 return 0;
432}
433
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000434int32_t RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000435 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000436 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000437 cName[RTCP_CNAME_SIZE - 1] = 0;
438 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000439 return 0;
440}
441
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000442int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000443 if (!cName)
444 return -1;
445
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000446 CriticalSectionScoped lock(_criticalSectionRTCPSender);
447 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
448 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
449 return 0;
450}
451
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000452int32_t RTCPSender::AddMixedCNAME(const uint32_t SSRC,
453 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000454 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000455 CriticalSectionScoped lock(_criticalSectionRTCPSender);
456 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
457 return -1;
458 }
459 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000460 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
461 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000462 _csrcCNAMEs[SSRC] = ptr;
463 return 0;
464}
465
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000466int32_t RTCPSender::RemoveMixedCNAME(const uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000467 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000468 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000469 _csrcCNAMEs.find(SSRC);
470
471 if (it == _csrcCNAMEs.end()) {
472 return -1;
473 }
474 delete it->second;
475 _csrcCNAMEs.erase(it);
476 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000477}
478
479bool
480RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
481{
482/*
483 For audio we use a fix 5 sec interval
484
485 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
486 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
487
488
489From RFC 3550
490
491 MAX RTCP BW is 5% if the session BW
492 A send report is approximately 65 bytes inc CNAME
493 A report report is approximately 28 bytes
494
495 The RECOMMENDED value for the reduced minimum in seconds is 360
496 divided by the session bandwidth in kilobits/second. This minimum
497 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
498
499 If the participant has not yet sent an RTCP packet (the variable
500 initial is true), the constant Tmin is set to 2.5 seconds, else it
501 is set to 5 seconds.
502
503 The interval between RTCP packets is varied randomly over the
504 range [0.5,1.5] times the calculated interval to avoid unintended
505 synchronization of all participants
506
507 if we send
508 If the participant is a sender (we_sent true), the constant C is
509 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
510 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
511 number of senders.
512
513 if we receive only
514 If we_sent is not true, the constant C is set
515 to the average RTCP packet size divided by 75% of the RTCP
516 bandwidth. The constant n is set to the number of receivers
517 (members - senders). If the number of senders is greater than
518 25%, senders and receivers are treated together.
519
520 reconsideration NOT required for peer-to-peer
521 "timer reconsideration" is
522 employed. This algorithm implements a simple back-off mechanism
523 which causes users to hold back RTCP packet transmission if the
524 group sizes are increasing.
525
526 n = number of members
527 C = avg_size/(rtcpBW/4)
528
529 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
530
531 4. The calculated interval T is set to a number uniformly distributed
532 between 0.5 and 1.5 times the deterministic calculated interval.
533
534 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
535 for the fact that the timer reconsideration algorithm converges to
536 a value of the RTCP bandwidth below the intended average
537*/
538
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000539 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000540
541 CriticalSectionScoped lock(_criticalSectionRTCPSender);
542
niklase@google.com470e71d2011-07-07 08:21:25 +0000543 if(_method == kRtcpOff)
544 {
545 return false;
546 }
547
niklase@google.com470e71d2011-07-07 08:21:25 +0000548 if(!_audio && sendKeyframeBeforeRTP)
549 {
550 // for video key-frames we want to send the RTCP before the large key-frame
551 // if we have a 100 ms margin
552 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
553 }
554
555 if(now > _nextTimeToSendRTCP)
556 {
557 return true;
558
559 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
560 {
561 // wrap
562 return true;
563 }
564 return false;
565}
566
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000567uint32_t
568RTCPSender::LastSendReport( uint32_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000569{
570 CriticalSectionScoped lock(_criticalSectionRTCPSender);
571
572 lastRTCPTime = _lastRTCPTime[0];
573 return _lastSendReport[0];
574}
575
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000576uint32_t
577RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
niklase@google.com470e71d2011-07-07 08:21:25 +0000578{
579 CriticalSectionScoped lock(_criticalSectionRTCPSender);
580
581 // This is only saved when we are the sender
582 if((_lastSendReport[0] == 0) || (sendReport == 0))
583 {
584 return 0; // will be ignored
585 } else
586 {
587 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
588 {
589 if( _lastSendReport[i] == sendReport)
590 {
591 return _lastRTCPTime[i];
592 }
593 }
594 }
595 return 0;
596}
597
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000598bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
599 int64_t* time_ms) const {
600 CriticalSectionScoped lock(_criticalSectionRTCPSender);
601
602 if (last_xr_rr_.empty()) {
603 return false;
604 }
605 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
606 if (it == last_xr_rr_.end()) {
607 return false;
608 }
609 *time_ms = it->second;
610 return true;
611}
612
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000613void RTCPSender::GetPacketTypeCounter(
614 RtcpPacketTypeCounter* packet_counter) const {
615 CriticalSectionScoped lock(_criticalSectionRTCPSender);
616 *packet_counter = packet_type_counter_;
617}
618
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000619int32_t RTCPSender::AddExternalReportBlock(
620 uint32_t SSRC,
621 const RTCPReportBlock* reportBlock) {
622 CriticalSectionScoped lock(_criticalSectionRTCPSender);
623 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
624}
625
626int32_t RTCPSender::AddReportBlock(
627 uint32_t SSRC,
628 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
629 const RTCPReportBlock* reportBlock) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000630 if (reportBlock == NULL) {
631 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
632 "%s invalid argument", __FUNCTION__);
633 return -1;
634 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000635
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000636 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000637 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
638 "%s invalid argument", __FUNCTION__);
639 return -1;
640 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000641 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000642 report_blocks->find(SSRC);
643 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000644 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000645 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000646 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000647 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
648 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000649 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000650 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000651}
652
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000653int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000654 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000655
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000656 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000657 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000658
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000659 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000660 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000661 }
662 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000663 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000664 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000665}
666
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000667int32_t RTCPSender::BuildSR(const FeedbackState& feedback_state,
668 uint8_t* rtcpbuffer,
669 int& pos,
670 uint32_t NTPsec,
671 uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000672{
673 // sanity
674 if(pos + 52 >= IP_PACKET_SIZE)
675 {
676 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
677 return -2;
678 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000679 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000680
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000681 uint32_t posNumberOfReportBlocks = pos;
682 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000683
684 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000685 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000686
687 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
688 {
689 // shift old
690 _lastSendReport[i+1] = _lastSendReport[i];
691 _lastRTCPTime[i+1] =_lastRTCPTime[i];
692 }
693
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000694 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000695 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000696
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000697 // The timestamp of this RTCP packet should be estimated as the timestamp of
698 // the frame being captured at this moment. We are calculating that
699 // timestamp as the last frame's timestamp + the time since the last frame
700 // was captured.
701 {
702 // Needs protection since this method is called on the process thread.
703 CriticalSectionScoped lock(_criticalSectionRTCPSender);
704 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
705 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000706 (feedback_state.frequency_hz / 1000);
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000707 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000708
709 // Add sender data
710 // Save for our length field
711 pos++;
712 pos++;
713
714 // Add our own SSRC
715 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
716 pos += 4;
717 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000718 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000719 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000720 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000721 pos += 4;
722 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
723 pos += 4;
724
725 //sender's packet count
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000726 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
727 feedback_state.packet_count_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000728 pos += 4;
729
730 //sender's octet count
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000731 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
732 feedback_state.byte_count_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000733 pos += 4;
734
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000735 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000736 int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
737 numberOfReportBlocks,
738 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000739 if(retVal < 0)
740 {
741 //
742 return retVal ;
743 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000744 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000745 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
746
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000747 uint16_t len = uint16_t((pos/4) -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000748 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
749 return 0;
750}
751
752
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000753int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000754 size_t lengthCname = strlen(_CNAME);
755 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000756
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000757 // sanity
758 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
759 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
760 "%s invalid argument", __FUNCTION__);
761 return -2;
762 }
763 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000764
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000765 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000766 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
767 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000768
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000769 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000770 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000771 pos++;
772 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000773
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000774 // Add our own SSRC
775 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
776 pos += 4;
777
778 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000779 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000780
781 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000782 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000783
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000784 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000785
786 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
787 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000788 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000789
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000790 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000791 // We must have a zero field even if we have an even multiple of 4 bytes
792 if ((pos % 4) == 0) {
793 padding++;
794 rtcpbuffer[pos++]=0;
795 }
796 while ((pos % 4) != 0) {
797 padding++;
798 rtcpbuffer[pos++]=0;
799 }
800 SDESLength += padding;
801
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000802 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000803 _csrcCNAMEs.begin();
804
805 for(; it != _csrcCNAMEs.end(); it++) {
806 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000807 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000808
809 // Add SSRC
810 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000811 pos += 4;
812
813 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000814 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000815
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000816 size_t length = strlen(cname->name);
817 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000818
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000819 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000820 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000821
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000822 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000823
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000824 pos += length;
825 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000826 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000827
828 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000829 if((pos % 4) == 0){
830 padding++;
831 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000832 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000833 while((pos % 4) != 0){
834 padding++;
835 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000836 }
837 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000838 }
839 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000840 uint16_t buffer_length = (SDESLength / 4) - 1;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000841 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
842 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000843 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000844}
845
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000846int32_t
847RTCPSender::BuildRR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000848 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000849 const uint32_t NTPsec,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000850 const uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000851{
852 // sanity one block
853 if(pos + 32 >= IP_PACKET_SIZE)
854 {
855 return -2;
856 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000857 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000858
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000859 rtcpbuffer[pos++]=(uint8_t)0x80;
860 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000861
862 // Save for our length field
863 pos++;
864 pos++;
865
866 // Add our own SSRC
867 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
868 pos += 4;
869
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000870 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000871 int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
872 numberOfReportBlocks,
873 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000874 if(retVal < 0)
875 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000876 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000877 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000878 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000879 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
880
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000881 uint16_t len = uint16_t((pos)/4 -1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000882 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
883 return 0;
884}
885
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000886// From RFC 5450: Transmission Time Offsets in RTP Streams.
887// 0 1 2 3
888// 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
889// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
890// hdr |V=2|P| RC | PT=IJ=195 | length |
891// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
892// | inter-arrival jitter |
893// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
894// . .
895// . .
896// . .
897// | inter-arrival jitter |
898// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
899//
900// If present, this RTCP packet must be placed after a receiver report
901// (inside a compound RTCP packet), and MUST have the same value for RC
902// (reception report count) as the receiver report.
903
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000904int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000905RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000906 uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000907 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000908 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000909{
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000910 if (external_report_blocks_.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000911 {
912 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
913 return 0;
914 }
915
916 // sanity
917 if(pos + 8 >= IP_PACKET_SIZE)
918 {
919 return -2;
920 }
921 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000922 uint8_t RC = 1;
923 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
924 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000925
926 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000927 rtcpbuffer[pos++]=(uint8_t)0;
928 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000929
930 // Add inter-arrival jitter
931 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
932 jitterTransmissionTimeOffset);
933 pos += 4;
934 return 0;
935}
936
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000937int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000938RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000939{
940 // sanity
941 if(pos + 12 >= IP_PACKET_SIZE)
942 {
943 return -2;
944 }
945 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000946 uint8_t FMT = 1;
947 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
948 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000949
950 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000951 rtcpbuffer[pos++]=(uint8_t)0;
952 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000953
954 // Add our own SSRC
955 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
956 pos += 4;
957
958 // Add the remote SSRC
959 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
960 pos += 4;
961 return 0;
962}
963
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000964int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000965 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000966 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000967 // sanity
968 if(pos + 20 >= IP_PACKET_SIZE) {
969 return -2;
970 }
971 if (!repeat) {
972 _sequenceNumberFIR++; // do not increase if repetition
973 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000974
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000975 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000976 uint8_t FMT = 4;
977 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
978 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000979
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000980 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000981 rtcpbuffer[pos++] = (uint8_t)0;
982 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000983
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000984 // Add our own SSRC
985 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
986 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000987
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000988 // RFC 5104 4.3.1.2. Semantics
989 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000990 rtcpbuffer[pos++] = (uint8_t)0;
991 rtcpbuffer[pos++] = (uint8_t)0;
992 rtcpbuffer[pos++] = (uint8_t)0;
993 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000994
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000995 // Additional Feedback Control Information (FCI)
996 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
997 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000998
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000999 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
1000 rtcpbuffer[pos++] = (uint8_t)0;
1001 rtcpbuffer[pos++] = (uint8_t)0;
1002 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001003 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001004}
1005
1006/*
1007 0 1 2 3
1008 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
1009 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1010 | First | Number | PictureID |
1011 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1012*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001013int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001014RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID)
niklase@google.com470e71d2011-07-07 08:21:25 +00001015{
1016 // sanity
1017 if(pos + 16 >= IP_PACKET_SIZE)
1018 {
1019 return -2;
1020 }
1021 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001022 uint8_t FMT = 2;
1023 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1024 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001025
1026 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001027 rtcpbuffer[pos++]=(uint8_t)0;
1028 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +00001029
1030 // Add our own SSRC
1031 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1032 pos += 4;
1033
1034 // Add the remote SSRC
1035 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1036 pos += 4;
1037
1038 // Add first, number & picture ID 6 bits
1039 // first = 0, 13 - bits
1040 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001041 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
niklase@google.com470e71d2011-07-07 08:21:25 +00001042 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
1043 pos += 4;
1044 return 0;
1045}
1046
1047/*
1048 0 1 2 3
1049 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
1050 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1051 | PB |0| Payload Type| Native RPSI bit string |
1052 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1053 | defined per codec ... | Padding (0) |
1054 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1055*/
1056/*
1057* Note: not generic made for VP8
1058*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001059int32_t
1060RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001061 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001062 const uint64_t pictureID,
1063 const uint8_t payloadType)
niklase@google.com470e71d2011-07-07 08:21:25 +00001064{
1065 // sanity
1066 if(pos + 24 >= IP_PACKET_SIZE)
1067 {
1068 return -2;
1069 }
1070 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001071 uint8_t FMT = 3;
1072 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1073 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +00001074
1075 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001076 uint32_t bitsRequired = 7;
1077 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001078 while((pictureID>>bitsRequired) > 0)
1079 {
1080 bitsRequired += 7;
1081 bytesRequired++;
1082 }
1083
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001084 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +00001085 if(bytesRequired > 6)
1086 {
1087 size = 5;
1088 } else if(bytesRequired > 2)
1089 {
1090 size = 4;
1091 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001092 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001093 rtcpbuffer[pos++]=size;
1094
1095 // Add our own SSRC
1096 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1097 pos += 4;
1098
1099 // Add the remote SSRC
1100 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1101 pos += 4;
1102
1103 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001104 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001105 if(paddingBytes == 4)
1106 {
1107 paddingBytes = 0;
1108 }
1109 // add padding length in bits
1110 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1111 pos++;
1112
1113 // add payload type
1114 rtcpbuffer[pos] = payloadType;
1115 pos++;
1116
1117 // add picture ID
1118 for(int i = bytesRequired-1; i > 0; i--)
1119 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001120 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +00001121 pos++;
1122 }
1123 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001124 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +00001125 pos++;
1126
1127 // add padding
1128 for(int j = 0; j <paddingBytes; j++)
1129 {
1130 rtcpbuffer[pos] = 0;
1131 pos++;
1132 }
1133 return 0;
1134}
1135
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001136int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001137RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001138{
1139 // sanity
1140 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1141 {
1142 return -2;
1143 }
1144 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001145 uint8_t FMT = 15;
1146 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1147 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001148
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001149 rtcpbuffer[pos++]=(uint8_t)0;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001150 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1151
1152 // Add our own SSRC
1153 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1154 pos += 4;
1155
1156 // Remote SSRC must be 0
1157 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1158 pos += 4;
1159
1160 rtcpbuffer[pos++]='R';
1161 rtcpbuffer[pos++]='E';
1162 rtcpbuffer[pos++]='M';
1163 rtcpbuffer[pos++]='B';
1164
1165 rtcpbuffer[pos++] = _lengthRembSSRC;
1166 // 6 bit Exp
1167 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001168 uint8_t brExp = 0;
1169 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001170 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001171 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001172 {
1173 brExp = i;
1174 break;
1175 }
1176 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001177 const uint32_t brMantissa = (_rembBitrate >> brExp);
1178 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1179 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1180 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001181
1182 for (int i = 0; i < _lengthRembSSRC; i++)
1183 {
1184 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1185 pos += 4;
1186 }
1187 return 0;
1188}
1189
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001190void
1191RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001192{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001193 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001194 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001195}
1196
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001197int32_t RTCPSender::BuildTMMBR(ModuleRtpRtcpImpl* rtp_rtcp_module,
1198 uint8_t* rtcpbuffer,
1199 int& pos) {
1200 if (rtp_rtcp_module == NULL)
1201 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001202 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1203 // If the sender is an owner of the TMMBN -> send TMMBR
1204 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1205
niklase@google.com470e71d2011-07-07 08:21:25 +00001206 // get current bounding set from RTCP receiver
1207 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001208 // store in candidateSet, allocates one extra slot
1209 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001210
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001211 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1212 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1213 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001214 int32_t lengthOfBoundingSet =
1215 rtp_rtcp_module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001216
1217 if(lengthOfBoundingSet > 0)
1218 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001219 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001220 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001221 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1222 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001223 {
1224 // do not send the same tuple
1225 return 0;
1226 }
1227 }
1228 if(!tmmbrOwner)
1229 {
1230 // use received bounding set as candidate set
1231 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001232 candidateSet->SetEntry(lengthOfBoundingSet,
1233 _tmmbr_Send,
1234 _packetOH_Send,
1235 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001236 int numCandidates = lengthOfBoundingSet+ 1;
1237
1238 // find bounding set
1239 TMMBRSet* boundingSet = NULL;
1240 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1241 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1242 {
1243 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1244 }
1245 if(!tmmbrOwner)
1246 {
1247 // did not enter bounding set, no meaning to send this request
1248 return 0;
1249 }
1250 }
1251 }
1252
1253 if(_tmmbr_Send)
1254 {
1255 // sanity
1256 if(pos + 20 >= IP_PACKET_SIZE)
1257 {
1258 return -2;
1259 }
1260 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001261 uint8_t FMT = 3;
1262 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1263 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001264
1265 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001266 rtcpbuffer[pos++]=(uint8_t)0;
1267 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001268
1269 // Add our own SSRC
1270 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1271 pos += 4;
1272
1273 // RFC 5104 4.2.1.2. Semantics
1274
1275 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001276 rtcpbuffer[pos++]=(uint8_t)0;
1277 rtcpbuffer[pos++]=(uint8_t)0;
1278 rtcpbuffer[pos++]=(uint8_t)0;
1279 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001280
1281 // Additional Feedback Control Information (FCI)
1282 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1283 pos += 4;
1284
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001285 uint32_t bitRate = _tmmbr_Send*1000;
1286 uint32_t mmbrExp = 0;
1287 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001288 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001289 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001290 {
1291 mmbrExp = i;
1292 break;
1293 }
1294 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001295 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001296
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001297 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1298 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1299 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1300 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001301 }
1302 return 0;
1303}
1304
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001305int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001306RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001307{
1308 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1309 if(boundingSet == NULL)
1310 {
1311 return -1;
1312 }
1313 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001314 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001315 {
1316 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1317 return -2;
1318 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001319 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001320 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001321 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1322 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001323
1324 //Add length later
1325 int posLength = pos;
1326 pos++;
1327 pos++;
1328
1329 // Add our own SSRC
1330 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1331 pos += 4;
1332
1333 // RFC 5104 4.2.2.2. Semantics
1334
1335 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001336 rtcpbuffer[pos++]=(uint8_t)0;
1337 rtcpbuffer[pos++]=(uint8_t)0;
1338 rtcpbuffer[pos++]=(uint8_t)0;
1339 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001340
1341 // Additional Feedback Control Information (FCI)
1342 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001343 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001344 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001345 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001346 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001347 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001348 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1349 pos += 4;
1350
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001351 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1352 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001353 for(int i=0; i<64; i++)
1354 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001355 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001356 {
1357 mmbrExp = i;
1358 break;
1359 }
1360 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001361 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1362 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001363
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001364 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1365 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1366 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1367 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001368 numBoundingSet++;
1369 }
1370 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001371 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1372 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1373 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001374 return 0;
1375}
1376
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001377int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001378RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001379{
1380 // sanity
1381 if(_appData == NULL)
1382 {
1383 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1384 return -1;
1385 }
1386 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1387 {
1388 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1389 return -2;
1390 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001391 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001392
1393 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001394 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001395
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001396 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1397 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1398 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001399
1400 // Add our own SSRC
1401 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1402 pos += 4;
1403
1404 // Add our application name
1405 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1406 pos += 4;
1407
1408 // Add the data
1409 memcpy(rtcpbuffer +pos, _appData,_appLength);
1410 pos += _appLength;
1411 return 0;
1412}
1413
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001414int32_t
1415RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001416 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001417 const int32_t nackSize,
1418 const uint16_t* nackList,
edjee@google.com79b02892013-04-04 19:43:34 +00001419 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001420{
1421 // sanity
1422 if(pos + 16 >= IP_PACKET_SIZE)
1423 {
1424 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1425 return -2;
1426 }
1427
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001428 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001429 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001430 uint8_t FMT = 1;
1431 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1432 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001433
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001434 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001435 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001436 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001437
1438 // Add our own SSRC
1439 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1440 pos += 4;
1441
1442 // Add the remote SSRC
1443 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1444 pos += 4;
1445
edjee@google.com79b02892013-04-04 19:43:34 +00001446 NACKStringBuilder stringBuilder;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001447 // Build NACK bitmasks and write them to the RTCP message.
1448 // The nack list should be sorted and not contain duplicates if one
1449 // wants to build the smallest rtcp nack packet.
1450 int numOfNackFields = 0;
1451 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1452 (IP_PACKET_SIZE - pos) / 4);
1453 int i = 0;
1454 while (i < nackSize && numOfNackFields < maxNackFields) {
1455 stringBuilder.PushNACK(nackList[i]);
1456 uint16_t nack = nackList[i++];
1457 uint16_t bitmask = 0;
1458 while (i < nackSize) {
1459 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1460 if (shift >= 0 && shift <= 15) {
1461 stringBuilder.PushNACK(nackList[i]);
1462 bitmask |= (1 << shift);
1463 ++i;
1464 } else {
1465 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001466 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001467 }
1468 // Write the sequence number and the bitmask to the packet.
1469 assert(pos + 4 < IP_PACKET_SIZE);
1470 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
1471 pos += 2;
1472 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
1473 pos += 2;
1474 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001475 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001476 if (i != nackSize) {
1477 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1478 "Nack list to large for one packet.");
1479 }
1480 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001481 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001482 return 0;
1483}
1484
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001485int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001486RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001487{
1488 // sanity
1489 if(pos + 8 >= IP_PACKET_SIZE)
1490 {
1491 return -2;
1492 }
1493 if(_includeCSRCs)
1494 {
1495 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001496 rtcpbuffer[pos++]=(uint8_t)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1497 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001498
1499 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001500 rtcpbuffer[pos++]=(uint8_t)0;
1501 rtcpbuffer[pos++]=(uint8_t)(1 + _CSRCs);
niklase@google.com470e71d2011-07-07 08:21:25 +00001502
1503 // Add our own SSRC
1504 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1505 pos += 4;
1506
1507 // add CSRCs
1508 for(int i = 0; i < _CSRCs; i++)
1509 {
1510 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1511 pos += 4;
1512 }
1513 } else
1514 {
1515 // Add a bye packet
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001516 rtcpbuffer[pos++]=(uint8_t)0x80 + 1; // number of SSRC+CSRCs
1517 rtcpbuffer[pos++]=(uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001518
1519 // length
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001520 rtcpbuffer[pos++]=(uint8_t)0;
1521 rtcpbuffer[pos++]=(uint8_t)1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001522
1523 // Add our own SSRC
1524 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1525 pos += 4;
1526 }
1527 return 0;
1528}
1529
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001530int32_t RTCPSender::BuildReceiverReferenceTime(uint8_t* buffer,
1531 int& pos,
1532 uint32_t ntp_sec,
1533 uint32_t ntp_frac) {
1534 const int kRrTimeBlockLength = 20;
1535 if (pos + kRrTimeBlockLength >= IP_PACKET_SIZE) {
1536 return -2;
1537 }
1538
1539 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) {
1540 last_xr_rr_.erase(last_xr_rr_.begin());
1541 }
1542 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
1543 RTCPUtility::MidNtp(ntp_sec, ntp_frac),
1544 Clock::NtpToMs(ntp_sec, ntp_frac)));
1545
1546 // Add XR header.
1547 buffer[pos++] = 0x80;
1548 buffer[pos++] = 207;
1549 buffer[pos++] = 0; // XR packet length.
1550 buffer[pos++] = 4; // XR packet length.
1551
1552 // Add our own SSRC.
1553 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
1554 pos += 4;
1555
1556 // 0 1 2 3
1557 // 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
1558 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1559 // | BT=4 | reserved | block length = 2 |
1560 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1561 // | NTP timestamp, most significant word |
1562 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1563 // | NTP timestamp, least significant word |
1564 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1565
1566 // Add Receiver Reference Time Report block.
1567 buffer[pos++] = 4; // BT.
1568 buffer[pos++] = 0; // Reserved.
1569 buffer[pos++] = 0; // Block length.
1570 buffer[pos++] = 2; // Block length.
1571
1572 // NTP timestamp.
1573 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, ntp_sec);
1574 pos += 4;
1575 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, ntp_frac);
1576 pos += 4;
1577
1578 return 0;
1579}
1580
1581int32_t RTCPSender::BuildDlrr(uint8_t* buffer,
1582 int& pos,
1583 const RtcpReceiveTimeInfo& info) {
1584 const int kDlrrBlockLength = 24;
1585 if (pos + kDlrrBlockLength >= IP_PACKET_SIZE) {
1586 return -2;
1587 }
1588
1589 // Add XR header.
1590 buffer[pos++] = 0x80;
1591 buffer[pos++] = 207;
1592 buffer[pos++] = 0; // XR packet length.
1593 buffer[pos++] = 5; // XR packet length.
1594
1595 // Add our own SSRC.
1596 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
1597 pos += 4;
1598
1599 // 0 1 2 3
1600 // 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
1601 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1602 // | BT=5 | reserved | block length |
1603 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1604 // | SSRC_1 (SSRC of first receiver) | sub-
1605 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1606 // | last RR (LRR) | 1
1607 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1608 // | delay since last RR (DLRR) |
1609 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1610 // | SSRC_2 (SSRC of second receiver) | sub-
1611 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1612 // : ... : 2
1613
1614 // Add DLRR sub block.
1615 buffer[pos++] = 5; // BT.
1616 buffer[pos++] = 0; // Reserved.
1617 buffer[pos++] = 0; // Block length.
1618 buffer[pos++] = 3; // Block length.
1619
1620 // NTP timestamp.
1621 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, info.sourceSSRC);
1622 pos += 4;
1623 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, info.lastRR);
1624 pos += 4;
1625 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + pos, info.delaySinceLastRR);
1626 pos += 4;
1627
1628 return 0;
1629}
1630
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001631int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001632RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001633{
1634 // sanity
1635 if(pos + 44 >= IP_PACKET_SIZE)
1636 {
1637 return -2;
1638 }
1639
1640 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001641 rtcpbuffer[pos++]=(uint8_t)0x80;
1642 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001643
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001644 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001645
1646 // handle length later on
1647 pos++;
1648 pos++;
1649
1650 // Add our own SSRC
1651 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1652 pos += 4;
1653
1654 // Add a VoIP metrics block
1655 rtcpbuffer[pos++]=7;
1656 rtcpbuffer[pos++]=0;
1657 rtcpbuffer[pos++]=0;
1658 rtcpbuffer[pos++]=8;
1659
1660 // Add the remote SSRC
1661 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1662 pos += 4;
1663
1664 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1665 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1666 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1667 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1668
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001669 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1670 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1671 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1672 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001673
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001674 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1675 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1676 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1677 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001678
1679 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1680 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1681 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1682 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1683
1684 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1685 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1686 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1687 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1688
1689 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1690 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001691 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1692 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001693
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001694 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1695 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1696 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1697 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001698
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001699 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1700 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001701 return 0;
1702}
1703
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001704int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
1705 uint32_t packetTypeFlags,
1706 int32_t nackSize,
1707 const uint16_t* nackList,
1708 bool repeat,
1709 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001710 {
1711 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1712 if(_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001713 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001714 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1715 "%s invalid state", __FUNCTION__);
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001716 return -1;
1717 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001718 }
1719 uint8_t rtcp_buffer[IP_PACKET_SIZE];
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001720 int rtcp_length = PrepareRTCP(feedback_state,
1721 packetTypeFlags,
1722 nackSize,
1723 nackList,
1724 repeat,
1725 pictureID,
1726 rtcp_buffer,
1727 IP_PACKET_SIZE);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001728 if (rtcp_length < 0) {
1729 return -1;
1730 }
1731 // Sanity don't send empty packets.
1732 if (rtcp_length == 0)
1733 {
1734 return -1;
1735 }
1736 return SendToNetwork(rtcp_buffer, static_cast<uint16_t>(rtcp_length));
1737}
1738
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001739int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
1740 uint32_t packetTypeFlags,
1741 int32_t nackSize,
1742 const uint16_t* nackList,
1743 bool repeat,
1744 uint64_t pictureID,
1745 uint8_t* rtcp_buffer,
1746 int buffer_size) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001747 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1748 // Collect the received information.
1749 uint32_t NTPsec = 0;
1750 uint32_t NTPfrac = 0;
1751 uint32_t jitterTransmissionOffset = 0;
1752 int position = 0;
1753
1754 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1755
1756 if(_TMMBR ) // Attach TMMBR to send and receive reports.
1757 {
1758 rtcpPacketTypeFlags |= kRtcpTmmbr;
1759 }
1760 if(_appSend)
1761 {
1762 rtcpPacketTypeFlags |= kRtcpApp;
1763 _appSend = false;
1764 }
1765 if(_REMB && _sendREMB)
1766 {
1767 // Always attach REMB to SR if that is configured. Note that REMB is
1768 // only sent on one of the RTP modules in the REMB group.
1769 rtcpPacketTypeFlags |= kRtcpRemb;
1770 }
1771 if(_xrSendVoIPMetric)
1772 {
1773 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1774 _xrSendVoIPMetric = false;
1775 }
1776 if(_sendTMMBN) // Set when having received a TMMBR.
1777 {
1778 rtcpPacketTypeFlags |= kRtcpTmmbn;
1779 _sendTMMBN = false;
1780 }
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001781 if (rtcpPacketTypeFlags & kRtcpReport)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001782 {
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001783 if (xrSendReceiverReferenceTimeEnabled_ && !_sending)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001784 {
1785 rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
1786 }
1787 if (feedback_state.has_last_xr_rr)
1788 {
1789 rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
1790 }
1791 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001792 if(_method == kRtcpCompound)
1793 {
1794 if(_sending)
1795 {
1796 rtcpPacketTypeFlags |= kRtcpSr;
1797 } else
1798 {
1799 rtcpPacketTypeFlags |= kRtcpRr;
1800 }
1801 } else if(_method == kRtcpNonCompound)
1802 {
1803 if(rtcpPacketTypeFlags & kRtcpReport)
1804 {
1805 if(_sending)
1806 {
1807 rtcpPacketTypeFlags |= kRtcpSr;
1808 } else
1809 {
1810 rtcpPacketTypeFlags |= kRtcpRr;
1811 }
1812 }
1813 }
1814 if( rtcpPacketTypeFlags & kRtcpRr ||
1815 rtcpPacketTypeFlags & kRtcpSr)
1816 {
1817 // generate next time to send a RTCP report
1818 // seeded from RTP constructor
1819 int32_t random = rand() % 1000;
1820 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1821
1822 if(_audio)
1823 {
1824 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1825 (RTCP_INTERVAL_AUDIO_MS*random/1000);
1826 }else
1827 {
1828 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1829 if(_sending)
1830 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001831 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1832 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1833 if (send_bitrate_kbit != 0)
1834 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001835 }
1836 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1837 {
1838 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1839 }
1840 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1841 }
1842 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1843 }
1844
1845 // If the data does not fit in the packet we fill it as much as possible.
1846 int32_t buildVal = 0;
1847
1848 // We need to send our NTP even if we haven't received any reports.
1849 _clock->CurrentNtp(NTPsec, NTPfrac);
1850 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1851 StatisticianMap statisticians =
1852 receive_statistics_->GetActiveStatisticians();
1853 if (!statisticians.empty()) {
1854 StatisticianMap::const_iterator it;
1855 int i;
1856 for (it = statisticians.begin(), i = 0; it != statisticians.end();
1857 ++it, ++i) {
1858 RTCPReportBlock report_block;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001859 if (PrepareReport(
1860 feedback_state, it->second, &report_block, &NTPsec, &NTPfrac))
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001861 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1862 }
1863 if (_IJ && !statisticians.empty()) {
1864 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1865 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001866 }
1867 }
1868
1869 if(rtcpPacketTypeFlags & kRtcpSr)
1870 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001871 buildVal = BuildSR(feedback_state, rtcp_buffer, position, NTPsec, NTPfrac);
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 buildVal = BuildSDEC(rtcp_buffer, position);
1878 if (buildVal == -1) {
1879 return -1;
1880 } else if (buildVal == -2) {
1881 return position;
1882 }
1883 }else if(rtcpPacketTypeFlags & kRtcpRr)
1884 {
1885 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1886 if (buildVal == -1) {
1887 return -1;
1888 } else if (buildVal == -2) {
1889 return position;
1890 }
1891 // only of set
1892 if(_CNAME[0] != 0)
1893 {
1894 buildVal = BuildSDEC(rtcp_buffer, position);
1895 if (buildVal == -1) {
1896 return -1;
1897 }
1898 }
1899 }
1900 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1901 {
1902 // If present, this RTCP packet must be placed after a
1903 // receiver report.
1904 buildVal = BuildExtendedJitterReport(rtcp_buffer,
1905 position,
1906 jitterTransmissionOffset);
1907 if (buildVal == -1) {
1908 return -1;
1909 } else if (buildVal == -2) {
1910 return position;
1911 }
1912 }
1913 if(rtcpPacketTypeFlags & kRtcpPli)
1914 {
1915 buildVal = BuildPLI(rtcp_buffer, position);
1916 if (buildVal == -1) {
1917 return -1;
1918 } else if (buildVal == -2) {
1919 return position;
1920 }
1921 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001922 ++packet_type_counter_.pli_packets;
1923 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_PLICount", _SSRC,
1924 packet_type_counter_.pli_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001925 }
1926 if(rtcpPacketTypeFlags & kRtcpFir)
1927 {
1928 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1929 if (buildVal == -1) {
1930 return -1;
1931 } else if (buildVal == -2) {
1932 return position;
1933 }
1934 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001935 ++packet_type_counter_.fir_packets;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001936 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_FIRCount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001937 packet_type_counter_.fir_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001938 }
1939 if(rtcpPacketTypeFlags & kRtcpSli)
1940 {
1941 buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1942 if (buildVal == -1) {
1943 return -1;
1944 } else if (buildVal == -2) {
1945 return position;
1946 }
1947 }
1948 if(rtcpPacketTypeFlags & kRtcpRpsi)
1949 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001950 const int8_t payloadType = feedback_state.send_payload_type;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001951 if (payloadType == -1) {
1952 return -1;
1953 }
1954 buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1955 (uint8_t)payloadType);
1956 if (buildVal == -1) {
1957 return -1;
1958 } else if (buildVal == -2) {
1959 return position;
1960 }
1961 }
1962 if(rtcpPacketTypeFlags & kRtcpRemb)
1963 {
1964 buildVal = BuildREMB(rtcp_buffer, position);
1965 if (buildVal == -1) {
1966 return -1;
1967 } else if (buildVal == -2) {
1968 return position;
1969 }
1970 TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
1971 }
1972 if(rtcpPacketTypeFlags & kRtcpBye)
1973 {
1974 buildVal = BuildBYE(rtcp_buffer, position);
1975 if (buildVal == -1) {
1976 return -1;
1977 } else if (buildVal == -2) {
1978 return position;
1979 }
1980 }
1981 if(rtcpPacketTypeFlags & kRtcpApp)
1982 {
1983 buildVal = BuildAPP(rtcp_buffer, position);
1984 if (buildVal == -1) {
1985 return -1;
1986 } else if (buildVal == -2) {
1987 return position;
1988 }
1989 }
1990 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1991 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001992 buildVal = BuildTMMBR(feedback_state.module, rtcp_buffer, position);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001993 if (buildVal == -1) {
1994 return -1;
1995 } else if (buildVal == -2) {
1996 return position;
1997 }
1998 }
1999 if(rtcpPacketTypeFlags & kRtcpTmmbn)
2000 {
2001 buildVal = BuildTMMBN(rtcp_buffer, position);
2002 if (buildVal == -1) {
2003 return -1;
2004 } else if (buildVal == -2) {
2005 return position;
2006 }
2007 }
2008 if(rtcpPacketTypeFlags & kRtcpNack)
2009 {
2010 std::string nackString;
2011 buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
2012 &nackString);
2013 if (buildVal == -1) {
2014 return -1;
2015 } else if (buildVal == -2) {
2016 return position;
2017 }
2018 TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
2019 "nacks", TRACE_STR_COPY(nackString.c_str()));
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00002020 ++packet_type_counter_.nack_packets;
2021 TRACE_COUNTER_ID1("webrtc_rtp", "RTCP_NACKCount", _SSRC,
2022 packet_type_counter_.nack_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002023 }
2024 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
2025 {
2026 buildVal = BuildVoIPMetric(rtcp_buffer, position);
2027 if (buildVal == -1) {
2028 return -1;
2029 } else if (buildVal == -2) {
2030 return position;
2031 }
2032 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002033 if (rtcpPacketTypeFlags & kRtcpXrReceiverReferenceTime)
2034 {
2035 buildVal = BuildReceiverReferenceTime(rtcp_buffer,
2036 position,
2037 NTPsec,
2038 NTPfrac);
2039 if (buildVal == -1) {
2040 return -1;
2041 } else if (buildVal == -2) {
2042 return position;
2043 }
2044 }
2045 if (rtcpPacketTypeFlags & kRtcpXrDlrrReportBlock)
2046 {
2047 buildVal = BuildDlrr(rtcp_buffer, position, feedback_state.last_xr_rr);
2048 if (buildVal == -1) {
2049 return -1;
2050 } else if (buildVal == -2) {
2051 return position;
2052 }
2053 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002054 return position;
2055}
2056
2057bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
2058 return Status() == kRtcpCompound ||
2059 (rtcp_packet_type & kRtcpReport) ||
2060 (rtcp_packet_type & kRtcpSr) ||
2061 (rtcp_packet_type & kRtcpRr);
2062}
2063
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002064bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
2065 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002066 RTCPReportBlock* report_block,
2067 uint32_t* ntp_secs, uint32_t* ntp_frac) {
2068 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00002069 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002070 if (!statistician->GetStatistics(&stats, true))
2071 return false;
2072 report_block->fractionLost = stats.fraction_lost;
2073 report_block->cumulativeLost = stats.cumulative_lost;
2074 report_block->extendedHighSeqNum =
2075 stats.extended_max_sequence_number;
2076 report_block->jitter = stats.jitter;
2077
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002078 // get our NTP as late as possible to avoid a race
2079 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
2080
2081 // Delay since last received report
2082 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002083 if ((feedback_state.last_rr_ntp_secs != 0) ||
2084 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002085 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
2086 uint32_t now=*ntp_secs&0x0000FFFF;
2087 now <<=16;
2088 now += (*ntp_frac&0xffff0000)>>16;
2089
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002090 uint32_t receiveTime = feedback_state.last_rr_ntp_secs&0x0000FFFF;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002091 receiveTime <<=16;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002092 receiveTime += (feedback_state.last_rr_ntp_frac&0xffff0000)>>16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002093
2094 delaySinceLastReceivedSR = now-receiveTime;
2095 }
2096 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00002097 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002098 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00002099}
2100
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002101int32_t
2102RTCPSender::SendToNetwork(const uint8_t* dataBuffer,
2103 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002104{
2105 CriticalSectionScoped lock(_criticalSectionTransport);
2106 if(_cbTransport)
2107 {
2108 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
2109 {
2110 return 0;
2111 }
2112 }
2113 return -1;
2114}
2115
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002116int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002117RTCPSender::SetCSRCStatus(const bool include)
2118{
2119 _includeCSRCs = include;
2120 return 0;
2121}
2122
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002123int32_t
2124RTCPSender::SetCSRCs(const uint32_t arrOfCSRC[kRtpCsrcSize],
2125 const uint8_t arrLength)
niklase@google.com470e71d2011-07-07 08:21:25 +00002126{
2127 if(arrLength > kRtpCsrcSize)
2128 {
2129 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2130 assert(false);
2131 return -1;
2132 }
2133
2134 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2135
2136 for(int i = 0; i < arrLength;i++)
2137 {
2138 _CSRC[i] = arrOfCSRC[i];
2139 }
2140 _CSRCs = arrLength;
2141 return 0;
2142}
2143
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002144int32_t
2145RTCPSender::SetApplicationSpecificData(const uint8_t subType,
2146 const uint32_t name,
2147 const uint8_t* data,
2148 const uint16_t length)
niklase@google.com470e71d2011-07-07 08:21:25 +00002149{
2150 if(length %4 != 0)
2151 {
2152 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2153 return -1;
2154 }
2155 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2156
2157 if(_appData)
2158 {
2159 delete [] _appData;
2160 }
2161
2162 _appSend = true;
2163 _appSubType = subType;
2164 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002165 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00002166 _appLength = length;
2167 memcpy(_appData, data, length);
2168 return 0;
2169}
2170
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002171int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002172RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2173{
2174 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2175 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2176
2177 _xrSendVoIPMetric = true;
2178 return 0;
2179}
2180
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002181void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
2182 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2183 xrSendReceiverReferenceTimeEnabled_ = enable;
2184}
2185
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00002186bool RTCPSender::RtcpXrReceiverReferenceTime() const {
2187 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2188 return xrSendReceiverReferenceTimeEnabled_;
2189}
2190
niklase@google.com470e71d2011-07-07 08:21:25 +00002191// called under critsect _criticalSectionRTCPSender
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002192int32_t RTCPSender::WriteAllReportBlocksToBuffer(
2193 uint8_t* rtcpbuffer,
2194 int pos,
2195 uint8_t& numberOfReportBlocks,
2196 const uint32_t NTPsec,
2197 const uint32_t NTPfrac) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002198 // sanity one block
2199 if(pos + 24 >= IP_PACKET_SIZE) {
2200 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2201 "%s invalid argument", __FUNCTION__);
2202 return -1;
2203 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002204 numberOfReportBlocks = external_report_blocks_.size();
2205 numberOfReportBlocks += internal_report_blocks_.size();
2206 if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002207 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2208 "%s invalid argument", __FUNCTION__);
2209 return -1;
2210 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002211 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2212 while (!internal_report_blocks_.empty()) {
2213 delete internal_report_blocks_.begin()->second;
2214 internal_report_blocks_.erase(internal_report_blocks_.begin());
2215 }
2216 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2217 return pos;
2218}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002219
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002220int32_t RTCPSender::WriteReportBlocksToBuffer(
2221 uint8_t* rtcpbuffer,
2222 int32_t position,
2223 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2224 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2225 report_blocks.begin();
2226 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002227 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002228 RTCPReportBlock* reportBlock = it->second;
2229 if (reportBlock) {
2230 // Remote SSRC
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002231 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position, remoteSSRC);
2232 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002233
2234 // fraction lost
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002235 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002236
2237 // cumulative loss
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002238 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002239 reportBlock->cumulativeLost);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002240 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002241
2242 // extended highest seq_no, contain the highest sequence number received
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002243 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002244 reportBlock->extendedHighSeqNum);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002245 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002246
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002247 // Jitter
2248 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002249 reportBlock->jitter);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002250 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002251
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002252 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002253 reportBlock->lastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002254 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002255
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002256 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002257 reportBlock->delaySinceLastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002258 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002259 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002260 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002261 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00002262}
2263
2264// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002265int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00002266RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002267 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +00002268{
2269 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2270
2271 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2272 {
2273 _sendTMMBN = true;
2274 return 0;
2275 }
2276 return -1;
2277}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002278} // namespace webrtc