blob: 92b0be6dfa48a9f1e0127ae6d525465a5064589c [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
11#include "rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000013#include <cassert> // assert
14#include <cstdlib> // rand
15#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
niklase@google.com470e71d2011-07-07 08:21:25 +000017#include "common_types.h"
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000018#include "modules/rtp_rtcp/source/rtp_rtcp_impl.h"
19#include "system_wrappers/interface/critical_section_wrapper.h"
20#include "system_wrappers/interface/trace.h"
edjee@google.com79b02892013-04-04 19:43:34 +000021#include "system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000022
niklase@google.com470e71d2011-07-07 08:21:25 +000023namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000024
25using RTCPUtility::RTCPCnameInformation;
26
edjee@google.com79b02892013-04-04 19:43:34 +000027NACKStringBuilder::NACKStringBuilder() :
28 _stream(""), _count(0), _consecutive(false)
29{
30 // Empty.
31}
32
33void NACKStringBuilder::PushNACK(WebRtc_UWord16 nack)
34{
35 if (_count == 0)
36 {
37 _stream << nack;
38 } else if (nack == _prevNack + 1)
39 {
40 _consecutive = true;
41 } else
42 {
43 if (_consecutive)
44 {
45 _stream << "-" << _prevNack;
46 _consecutive = false;
47 }
48 _stream << "," << nack;
49 }
50 _count++;
51 _prevNack = nack;
52}
53
54std::string NACKStringBuilder::GetResult()
55{
56 if (_consecutive)
57 {
58 _stream << "-" << _prevNack;
59 _consecutive = false;
60 }
61 return _stream.str();
62}
63
niklase@google.com470e71d2011-07-07 08:21:25 +000064RTCPSender::RTCPSender(const WebRtc_Word32 id,
65 const bool audio,
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000066 Clock* clock,
pwestin@webrtc.org741da942011-09-20 13:52:04 +000067 ModuleRtpRtcpImpl* owner) :
niklase@google.com470e71d2011-07-07 08:21:25 +000068 _id(id),
69 _audio(audio),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000070 _clock(clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000071 _method(kRtcpOff),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000072 _rtpRtcp(*owner),
henrike@webrtc.org65573f22011-12-13 19:17:27 +000073 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000074 _cbTransport(NULL),
75
henrike@webrtc.org65573f22011-12-13 19:17:27 +000076 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000077 _usingNack(false),
78 _sending(false),
79 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000080 _REMB(false),
81 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000082 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +000083 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000084 _nextTimeToSendRTCP(0),
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000085 start_timestamp_(0),
86 last_rtp_timestamp_(0),
87 last_frame_capture_time_ms_(-1),
niklase@google.com470e71d2011-07-07 08:21:25 +000088 _SSRC(0),
89 _remoteSSRC(0),
90 _CNAME(),
91 _reportBlocks(),
92 _csrcCNAMEs(),
93
94 _cameraDelayMS(0),
95
96 _lastSendReport(),
97 _lastRTCPTime(),
98
99 _CSRCs(0),
100 _CSRC(),
101 _includeCSRCs(true),
102
103 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000104
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000105 _lengthRembSSRC(0),
106 _sizeRembSSRC(0),
107 _rembSSRC(NULL),
108 _rembBitrate(0),
109
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000110 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000111 _tmmbr_Send(0),
112 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000113
114 _appSend(false),
115 _appSubType(0),
116 _appName(),
117 _appData(NULL),
118 _appLength(0),
119 _xrSendVoIPMetric(false),
edjee@google.com79b02892013-04-04 19:43:34 +0000120 _xrVoIPMetric(),
121 _nackCount(0),
122 _pliCount(0),
123 _fullIntraRequestCount(0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000124{
125 memset(_CNAME, 0, sizeof(_CNAME));
126 memset(_lastSendReport, 0, sizeof(_lastSendReport));
127 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
128
129 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
130}
131
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000132RTCPSender::~RTCPSender() {
133 delete [] _rembSSRC;
134 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000135
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000136 while (!_reportBlocks.empty()) {
137 std::map<WebRtc_UWord32, RTCPReportBlock*>::iterator it =
138 _reportBlocks.begin();
139 delete it->second;
140 _reportBlocks.erase(it);
141 }
142 while (!_csrcCNAMEs.empty()) {
143 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator it =
144 _csrcCNAMEs.begin();
145 delete it->second;
146 _csrcCNAMEs.erase(it);
147 }
148 delete _criticalSectionTransport;
149 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000150
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000151 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000152}
153
154WebRtc_Word32
155RTCPSender::Init()
156{
157 CriticalSectionScoped lock(_criticalSectionRTCPSender);
158
159 _method = kRtcpOff;
160 _cbTransport = NULL;
161 _usingNack = false;
162 _sending = false;
163 _sendTMMBN = false;
164 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000165 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000166 _REMB = false;
167 _sendREMB = false;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000168 last_rtp_timestamp_ = 0;
169 last_frame_capture_time_ms_ = -1;
170 start_timestamp_ = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000171 _SSRC = 0;
172 _remoteSSRC = 0;
173 _cameraDelayMS = 0;
174 _sequenceNumberFIR = 0;
175 _tmmbr_Send = 0;
176 _packetOH_Send = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000177 _nextTimeToSendRTCP = 0;
178 _CSRCs = 0;
179 _appSend = false;
180 _appSubType = 0;
181
182 if(_appData)
183 {
184 delete [] _appData;
185 _appData = NULL;
186 }
187 _appLength = 0;
188
189 _xrSendVoIPMetric = false;
190
191 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
192 memset(_CNAME, 0, sizeof(_CNAME));
193 memset(_lastSendReport, 0, sizeof(_lastSendReport));
194 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
edjee@google.com79b02892013-04-04 19:43:34 +0000195
196 _nackCount = 0;
197 _pliCount = 0;
198 _fullIntraRequestCount = 0;
199
niklase@google.com470e71d2011-07-07 08:21:25 +0000200 return 0;
201}
202
203void
204RTCPSender::ChangeUniqueId(const WebRtc_Word32 id)
205{
206 _id = id;
207}
208
209WebRtc_Word32
210RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
211{
212 CriticalSectionScoped lock(_criticalSectionTransport);
213 _cbTransport = outgoingTransport;
214 return 0;
215}
216
217RTCPMethod
218RTCPSender::Status() const
219{
220 CriticalSectionScoped lock(_criticalSectionRTCPSender);
221 return _method;
222}
223
224WebRtc_Word32
225RTCPSender::SetRTCPStatus(const RTCPMethod method)
226{
227 CriticalSectionScoped lock(_criticalSectionRTCPSender);
228 if(method != kRtcpOff)
229 {
230 if(_audio)
231 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000232 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000233 (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000234 } else
235 {
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000236 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000237 (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000238 }
239 }
240 _method = method;
241 return 0;
242}
243
244bool
245RTCPSender::Sending() const
246{
247 CriticalSectionScoped lock(_criticalSectionRTCPSender);
248 return _sending;
249}
250
251WebRtc_Word32
252RTCPSender::SetSendingStatus(const bool sending)
253{
254 bool sendRTCPBye = false;
255 {
256 CriticalSectionScoped lock(_criticalSectionRTCPSender);
257
258 if(_method != kRtcpOff)
259 {
260 if(sending == false && _sending == true)
261 {
262 // Trigger RTCP bye
263 sendRTCPBye = true;
264 }
265 }
266 _sending = sending;
267 }
268 if(sendRTCPBye)
269 {
270 return SendRTCP(kRtcpBye);
271 }
272 return 0;
273}
274
275bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000276RTCPSender::REMB() const
277{
278 CriticalSectionScoped lock(_criticalSectionRTCPSender);
279 return _REMB;
280}
281
282WebRtc_Word32
283RTCPSender::SetREMBStatus(const bool enable)
284{
285 CriticalSectionScoped lock(_criticalSectionRTCPSender);
286 _REMB = enable;
287 return 0;
288}
289
290WebRtc_Word32
291RTCPSender::SetREMBData(const WebRtc_UWord32 bitrate,
292 const WebRtc_UWord8 numberOfSSRC,
293 const WebRtc_UWord32* SSRC)
294{
295 CriticalSectionScoped lock(_criticalSectionRTCPSender);
296 _rembBitrate = bitrate;
297
298 if(_sizeRembSSRC < numberOfSSRC)
299 {
300 delete [] _rembSSRC;
301 _rembSSRC = new WebRtc_UWord32[numberOfSSRC];
302 _sizeRembSSRC = numberOfSSRC;
303 }
304
305 _lengthRembSSRC = numberOfSSRC;
306 for (int i = 0; i < numberOfSSRC; i++)
307 {
308 _rembSSRC[i] = SSRC[i];
309 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000310 _sendREMB = true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000311 return 0;
312}
313
314bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000315RTCPSender::TMMBR() const
316{
317 CriticalSectionScoped lock(_criticalSectionRTCPSender);
318 return _TMMBR;
319}
320
321WebRtc_Word32
322RTCPSender::SetTMMBRStatus(const bool enable)
323{
324 CriticalSectionScoped lock(_criticalSectionRTCPSender);
325 _TMMBR = enable;
326 return 0;
327}
328
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000329bool
330RTCPSender::IJ() const
331{
332 CriticalSectionScoped lock(_criticalSectionRTCPSender);
333 return _IJ;
334}
335
336WebRtc_Word32
337RTCPSender::SetIJStatus(const bool enable)
338{
339 CriticalSectionScoped lock(_criticalSectionRTCPSender);
340 _IJ = enable;
341 return 0;
342}
343
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000344void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
345 start_timestamp_ = start_timestamp;
346}
347
348void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
349 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000350 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000351 last_rtp_timestamp_ = rtp_timestamp;
352 if (capture_time_ms < 0) {
353 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000354 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000355 } else {
356 last_frame_capture_time_ms_ = capture_time_ms;
357 }
358}
359
niklase@google.com470e71d2011-07-07 08:21:25 +0000360void
361RTCPSender::SetSSRC( const WebRtc_UWord32 ssrc)
362{
363 CriticalSectionScoped lock(_criticalSectionRTCPSender);
364
365 if(_SSRC != 0)
366 {
367 // not first SetSSRC, probably due to a collision
368 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000369 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000370 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000371 }
372 _SSRC = ssrc;
373}
374
375WebRtc_Word32
376RTCPSender::SetRemoteSSRC( const WebRtc_UWord32 ssrc)
377{
378 CriticalSectionScoped lock(_criticalSectionRTCPSender);
379 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000380 return 0;
381}
382
383WebRtc_Word32
384RTCPSender::SetCameraDelay(const WebRtc_Word32 delayMS)
385{
386 CriticalSectionScoped lock(_criticalSectionRTCPSender);
387 if(delayMS > 1000 || delayMS < -1000)
388 {
389 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
390 return -1;
391 }
392 _cameraDelayMS = delayMS;
393 return 0;
394}
395
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000396WebRtc_Word32 RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
397 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000398 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000399 cName[RTCP_CNAME_SIZE - 1] = 0;
400 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000401 return 0;
402}
403
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000404WebRtc_Word32 RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000405 if (!cName)
406 return -1;
407
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000408 CriticalSectionScoped lock(_criticalSectionRTCPSender);
409 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
410 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
411 return 0;
412}
413
414WebRtc_Word32 RTCPSender::AddMixedCNAME(const WebRtc_UWord32 SSRC,
415 const char cName[RTCP_CNAME_SIZE]) {
416 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000417 CriticalSectionScoped lock(_criticalSectionRTCPSender);
418 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
419 return -1;
420 }
421 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000422 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
423 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000424 _csrcCNAMEs[SSRC] = ptr;
425 return 0;
426}
427
428WebRtc_Word32 RTCPSender::RemoveMixedCNAME(const WebRtc_UWord32 SSRC) {
429 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000430 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator it =
431 _csrcCNAMEs.find(SSRC);
432
433 if (it == _csrcCNAMEs.end()) {
434 return -1;
435 }
436 delete it->second;
437 _csrcCNAMEs.erase(it);
438 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000439}
440
441bool
442RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
443{
444/*
445 For audio we use a fix 5 sec interval
446
447 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
448 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
449
450
451From RFC 3550
452
453 MAX RTCP BW is 5% if the session BW
454 A send report is approximately 65 bytes inc CNAME
455 A report report is approximately 28 bytes
456
457 The RECOMMENDED value for the reduced minimum in seconds is 360
458 divided by the session bandwidth in kilobits/second. This minimum
459 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
460
461 If the participant has not yet sent an RTCP packet (the variable
462 initial is true), the constant Tmin is set to 2.5 seconds, else it
463 is set to 5 seconds.
464
465 The interval between RTCP packets is varied randomly over the
466 range [0.5,1.5] times the calculated interval to avoid unintended
467 synchronization of all participants
468
469 if we send
470 If the participant is a sender (we_sent true), the constant C is
471 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
472 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
473 number of senders.
474
475 if we receive only
476 If we_sent is not true, the constant C is set
477 to the average RTCP packet size divided by 75% of the RTCP
478 bandwidth. The constant n is set to the number of receivers
479 (members - senders). If the number of senders is greater than
480 25%, senders and receivers are treated together.
481
482 reconsideration NOT required for peer-to-peer
483 "timer reconsideration" is
484 employed. This algorithm implements a simple back-off mechanism
485 which causes users to hold back RTCP packet transmission if the
486 group sizes are increasing.
487
488 n = number of members
489 C = avg_size/(rtcpBW/4)
490
491 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
492
493 4. The calculated interval T is set to a number uniformly distributed
494 between 0.5 and 1.5 times the deterministic calculated interval.
495
496 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
497 for the fact that the timer reconsideration algorithm converges to
498 a value of the RTCP bandwidth below the intended average
499*/
500
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000501 WebRtc_Word64 now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000502
503 CriticalSectionScoped lock(_criticalSectionRTCPSender);
504
niklase@google.com470e71d2011-07-07 08:21:25 +0000505 if(_method == kRtcpOff)
506 {
507 return false;
508 }
509
niklase@google.com470e71d2011-07-07 08:21:25 +0000510 if(!_audio && sendKeyframeBeforeRTP)
511 {
512 // for video key-frames we want to send the RTCP before the large key-frame
513 // if we have a 100 ms margin
514 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
515 }
516
517 if(now > _nextTimeToSendRTCP)
518 {
519 return true;
520
521 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
522 {
523 // wrap
524 return true;
525 }
526 return false;
527}
528
529WebRtc_UWord32
530RTCPSender::LastSendReport( WebRtc_UWord32& lastRTCPTime)
531{
532 CriticalSectionScoped lock(_criticalSectionRTCPSender);
533
534 lastRTCPTime = _lastRTCPTime[0];
535 return _lastSendReport[0];
536}
537
538WebRtc_UWord32
539RTCPSender::SendTimeOfSendReport(const WebRtc_UWord32 sendReport)
540{
541 CriticalSectionScoped lock(_criticalSectionRTCPSender);
542
543 // This is only saved when we are the sender
544 if((_lastSendReport[0] == 0) || (sendReport == 0))
545 {
546 return 0; // will be ignored
547 } else
548 {
549 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
550 {
551 if( _lastSendReport[i] == sendReport)
552 {
553 return _lastRTCPTime[i];
554 }
555 }
556 }
557 return 0;
558}
559
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000560WebRtc_Word32 RTCPSender::AddReportBlock(const WebRtc_UWord32 SSRC,
561 const RTCPReportBlock* reportBlock) {
562 if (reportBlock == NULL) {
563 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
564 "%s invalid argument", __FUNCTION__);
565 return -1;
566 }
567 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000568
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000569 if (_reportBlocks.size() >= RTCP_MAX_REPORT_BLOCKS) {
570 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
571 "%s invalid argument", __FUNCTION__);
572 return -1;
573 }
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000574 std::map<WebRtc_UWord32, RTCPReportBlock*>::iterator it =
575 _reportBlocks.find(SSRC);
576 if (it != _reportBlocks.end()) {
577 delete it->second;
578 _reportBlocks.erase(it);
579 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000580 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
581 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
582 _reportBlocks[SSRC] = copyReportBlock;
583 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000584}
585
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000586WebRtc_Word32 RTCPSender::RemoveReportBlock(const WebRtc_UWord32 SSRC) {
587 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000588
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000589 std::map<WebRtc_UWord32, RTCPReportBlock*>::iterator it =
590 _reportBlocks.find(SSRC);
591
592 if (it == _reportBlocks.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000593 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000594 }
595 delete it->second;
596 _reportBlocks.erase(it);
597 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000598}
599
600WebRtc_Word32
601RTCPSender::BuildSR(WebRtc_UWord8* rtcpbuffer,
602 WebRtc_UWord32& pos,
603 const WebRtc_UWord32 NTPsec,
604 const WebRtc_UWord32 NTPfrac,
605 const RTCPReportBlock* received)
606{
607 // sanity
608 if(pos + 52 >= IP_PACKET_SIZE)
609 {
610 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
611 return -2;
612 }
613 WebRtc_UWord32 RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000614
615 WebRtc_UWord32 posNumberOfReportBlocks = pos;
616 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
617
618 // Sender report
619 rtcpbuffer[pos++]=(WebRtc_UWord8)200;
620
621 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
622 {
623 // shift old
624 _lastSendReport[i+1] = _lastSendReport[i];
625 _lastRTCPTime[i+1] =_lastRTCPTime[i];
626 }
627
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000628 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac);
629 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000630
631 WebRtc_UWord32 freqHz = 90000; // For video
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000632 if(_audio) {
633 freqHz = _rtpRtcp.CurrentSendFrequencyHz();
niklase@google.com470e71d2011-07-07 08:21:25 +0000634 }
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000635
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000636 // The timestamp of this RTCP packet should be estimated as the timestamp of
637 // the frame being captured at this moment. We are calculating that
638 // timestamp as the last frame's timestamp + the time since the last frame
639 // was captured.
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000640 {
641 // Needs protection since this method is called on the process thread.
642 CriticalSectionScoped lock(_criticalSectionRTCPSender);
643 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (
644 _clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
645 (freqHz / 1000);
646 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000647
648 // Add sender data
649 // Save for our length field
650 pos++;
651 pos++;
652
653 // Add our own SSRC
654 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
655 pos += 4;
656 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000657 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000658 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000659 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000660 pos += 4;
661 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
662 pos += 4;
663
664 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000665 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000666 pos += 4;
667
668 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000669 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000670 pos += 4;
671
672 WebRtc_UWord8 numberOfReportBlocks = 0;
673 WebRtc_Word32 retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
674 if(retVal < 0)
675 {
676 //
677 return retVal ;
678 }
679 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
680
681 WebRtc_UWord16 len = WebRtc_UWord16((pos/4) -1);
682 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
683 return 0;
684}
685
686
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000687WebRtc_Word32 RTCPSender::BuildSDEC(WebRtc_UWord8* rtcpbuffer,
688 WebRtc_UWord32& pos) {
689 size_t lengthCname = strlen(_CNAME);
690 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000691
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000692 // sanity
693 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
694 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
695 "%s invalid argument", __FUNCTION__);
696 return -2;
697 }
698 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000699
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000700 // We always need to add SDES CNAME
701 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(0x80 + 1 + _csrcCNAMEs.size());
702 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000703
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000704 // handle SDES length later on
705 WebRtc_UWord32 SDESLengthPos = pos;
706 pos++;
707 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000708
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000709 // Add our own SSRC
710 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
711 pos += 4;
712
713 // CNAME = 1
714 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(1);
715
716 //
717 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(lengthCname);
718
719 WebRtc_UWord16 SDESLength = 10;
720
721 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
722 pos += lengthCname;
723 SDESLength += (WebRtc_UWord16)lengthCname;
724
725 WebRtc_UWord16 padding = 0;
726 // We must have a zero field even if we have an even multiple of 4 bytes
727 if ((pos % 4) == 0) {
728 padding++;
729 rtcpbuffer[pos++]=0;
730 }
731 while ((pos % 4) != 0) {
732 padding++;
733 rtcpbuffer[pos++]=0;
734 }
735 SDESLength += padding;
736
737 std::map<WebRtc_UWord32, RTCPUtility::RTCPCnameInformation*>::iterator it =
738 _csrcCNAMEs.begin();
739
740 for(; it != _csrcCNAMEs.end(); it++) {
741 RTCPCnameInformation* cname = it->second;
742 WebRtc_UWord32 SSRC = it->first;
743
744 // Add SSRC
745 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000746 pos += 4;
747
748 // CNAME = 1
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000749 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000750
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000751 size_t length = strlen(cname->name);
752 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000753
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000754 rtcpbuffer[pos++]= static_cast<WebRtc_UWord8>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000755 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000756
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000757 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000758
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000759 pos += length;
760 SDESLength += length;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000761 WebRtc_UWord16 padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000762
763 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000764 if((pos % 4) == 0){
765 padding++;
766 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000767 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000768 while((pos % 4) != 0){
769 padding++;
770 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000771 }
772 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000773 }
774 // in 32-bit words minus one and we don't count the header
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000775 WebRtc_UWord16 buffer_length = (SDESLength / 4) - 1;
776 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
777 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000778 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000779}
780
781WebRtc_Word32
782RTCPSender::BuildRR(WebRtc_UWord8* rtcpbuffer,
783 WebRtc_UWord32& pos,
784 const WebRtc_UWord32 NTPsec,
785 const WebRtc_UWord32 NTPfrac,
786 const RTCPReportBlock* received)
787{
788 // sanity one block
789 if(pos + 32 >= IP_PACKET_SIZE)
790 {
791 return -2;
792 }
793 WebRtc_UWord32 posNumberOfReportBlocks = pos;
794
795 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
796 rtcpbuffer[pos++]=(WebRtc_UWord8)201;
797
798 // Save for our length field
799 pos++;
800 pos++;
801
802 // Add our own SSRC
803 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
804 pos += 4;
805
806 WebRtc_UWord8 numberOfReportBlocks = 0;
807 WebRtc_Word32 retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
808 if(retVal < 0)
809 {
810 return retVal;
811 }
812 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
813
814 WebRtc_UWord16 len = WebRtc_UWord16((pos)/4 -1);
815 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
816 return 0;
817}
818
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000819// From RFC 5450: Transmission Time Offsets in RTP Streams.
820// 0 1 2 3
821// 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
822// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
823// hdr |V=2|P| RC | PT=IJ=195 | length |
824// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
825// | inter-arrival jitter |
826// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
827// . .
828// . .
829// . .
830// | inter-arrival jitter |
831// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
832//
833// If present, this RTCP packet must be placed after a receiver report
834// (inside a compound RTCP packet), and MUST have the same value for RC
835// (reception report count) as the receiver report.
836
837WebRtc_Word32
838RTCPSender::BuildExtendedJitterReport(
839 WebRtc_UWord8* rtcpbuffer,
840 WebRtc_UWord32& pos,
841 const WebRtc_UWord32 jitterTransmissionTimeOffset)
842{
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000843 if (_reportBlocks.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000844 {
845 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
846 return 0;
847 }
848
849 // sanity
850 if(pos + 8 >= IP_PACKET_SIZE)
851 {
852 return -2;
853 }
854 // add picture loss indicator
855 WebRtc_UWord8 RC = 1;
856 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + RC;
857 rtcpbuffer[pos++]=(WebRtc_UWord8)195;
858
859 // Used fixed length of 2
860 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
861 rtcpbuffer[pos++]=(WebRtc_UWord8)(1);
862
863 // Add inter-arrival jitter
864 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
865 jitterTransmissionTimeOffset);
866 pos += 4;
867 return 0;
868}
869
niklase@google.com470e71d2011-07-07 08:21:25 +0000870WebRtc_Word32
871RTCPSender::BuildPLI(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
872{
873 // sanity
874 if(pos + 12 >= IP_PACKET_SIZE)
875 {
876 return -2;
877 }
878 // add picture loss indicator
879 WebRtc_UWord8 FMT = 1;
880 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
881 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
882
883 //Used fixed length of 2
884 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
885 rtcpbuffer[pos++]=(WebRtc_UWord8)(2);
886
887 // Add our own SSRC
888 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
889 pos += 4;
890
891 // Add the remote SSRC
892 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
893 pos += 4;
894 return 0;
895}
896
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000897WebRtc_Word32 RTCPSender::BuildFIR(WebRtc_UWord8* rtcpbuffer,
898 WebRtc_UWord32& pos,
899 bool repeat) {
900 // sanity
901 if(pos + 20 >= IP_PACKET_SIZE) {
902 return -2;
903 }
904 if (!repeat) {
905 _sequenceNumberFIR++; // do not increase if repetition
906 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000907
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000908 // add full intra request indicator
909 WebRtc_UWord8 FMT = 4;
910 rtcpbuffer[pos++] = (WebRtc_UWord8)0x80 + FMT;
911 rtcpbuffer[pos++] = (WebRtc_UWord8)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000912
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000913 //Length of 4
914 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
915 rtcpbuffer[pos++] = (WebRtc_UWord8)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000916
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000917 // Add our own SSRC
918 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
919 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000920
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000921 // RFC 5104 4.3.1.2. Semantics
922 // SSRC of media source
923 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
924 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
925 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
926 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000927
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000928 // Additional Feedback Control Information (FCI)
929 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
930 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000931
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000932 rtcpbuffer[pos++] = (WebRtc_UWord8)(_sequenceNumberFIR);
933 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
934 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
935 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
936 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000937}
938
939/*
940 0 1 2 3
941 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
942 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
943 | First | Number | PictureID |
944 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
945*/
946WebRtc_Word32
947RTCPSender::BuildSLI(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos, const WebRtc_UWord8 pictureID)
948{
949 // sanity
950 if(pos + 16 >= IP_PACKET_SIZE)
951 {
952 return -2;
953 }
954 // add slice loss indicator
955 WebRtc_UWord8 FMT = 2;
956 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
957 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
958
959 //Used fixed length of 3
960 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
961 rtcpbuffer[pos++]=(WebRtc_UWord8)(3);
962
963 // Add our own SSRC
964 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
965 pos += 4;
966
967 // Add the remote SSRC
968 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
969 pos += 4;
970
971 // Add first, number & picture ID 6 bits
972 // first = 0, 13 - bits
973 // number = 0x1fff, 13 - bits only ones for now
974 WebRtc_UWord32 sliField = (0x1fff << 6)+ (0x3f & pictureID);
975 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
976 pos += 4;
977 return 0;
978}
979
980/*
981 0 1 2 3
982 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
983 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
984 | PB |0| Payload Type| Native RPSI bit string |
985 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
986 | defined per codec ... | Padding (0) |
987 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
988*/
989/*
990* Note: not generic made for VP8
991*/
992WebRtc_Word32
993RTCPSender::BuildRPSI(WebRtc_UWord8* rtcpbuffer,
994 WebRtc_UWord32& pos,
995 const WebRtc_UWord64 pictureID,
996 const WebRtc_UWord8 payloadType)
997{
998 // sanity
999 if(pos + 24 >= IP_PACKET_SIZE)
1000 {
1001 return -2;
1002 }
1003 // add Reference Picture Selection Indication
1004 WebRtc_UWord8 FMT = 3;
1005 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1006 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
1007
1008 // calc length
1009 WebRtc_UWord32 bitsRequired = 7;
1010 WebRtc_UWord8 bytesRequired = 1;
1011 while((pictureID>>bitsRequired) > 0)
1012 {
1013 bitsRequired += 7;
1014 bytesRequired++;
1015 }
1016
1017 WebRtc_UWord8 size = 3;
1018 if(bytesRequired > 6)
1019 {
1020 size = 5;
1021 } else if(bytesRequired > 2)
1022 {
1023 size = 4;
1024 }
1025 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1026 rtcpbuffer[pos++]=size;
1027
1028 // Add our own SSRC
1029 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1030 pos += 4;
1031
1032 // Add the remote SSRC
1033 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1034 pos += 4;
1035
1036 // calc padding length
1037 WebRtc_UWord8 paddingBytes = 4-((2+bytesRequired)%4);
1038 if(paddingBytes == 4)
1039 {
1040 paddingBytes = 0;
1041 }
1042 // add padding length in bits
1043 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1044 pos++;
1045
1046 // add payload type
1047 rtcpbuffer[pos] = payloadType;
1048 pos++;
1049
1050 // add picture ID
1051 for(int i = bytesRequired-1; i > 0; i--)
1052 {
1053 rtcpbuffer[pos] = 0x80 | WebRtc_UWord8(pictureID >> (i*7));
1054 pos++;
1055 }
1056 // add last byte of picture ID
1057 rtcpbuffer[pos] = WebRtc_UWord8(pictureID & 0x7f);
1058 pos++;
1059
1060 // add padding
1061 for(int j = 0; j <paddingBytes; j++)
1062 {
1063 rtcpbuffer[pos] = 0;
1064 pos++;
1065 }
1066 return 0;
1067}
1068
1069WebRtc_Word32
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001070RTCPSender::BuildREMB(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1071{
1072 // sanity
1073 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1074 {
1075 return -2;
1076 }
1077 // add application layer feedback
1078 WebRtc_UWord8 FMT = 15;
1079 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1080 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
1081
1082 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1083 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1084
1085 // Add our own SSRC
1086 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1087 pos += 4;
1088
1089 // Remote SSRC must be 0
1090 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1091 pos += 4;
1092
1093 rtcpbuffer[pos++]='R';
1094 rtcpbuffer[pos++]='E';
1095 rtcpbuffer[pos++]='M';
1096 rtcpbuffer[pos++]='B';
1097
1098 rtcpbuffer[pos++] = _lengthRembSSRC;
1099 // 6 bit Exp
1100 // 18 bit mantissa
1101 WebRtc_UWord8 brExp = 0;
1102 for(WebRtc_UWord32 i=0; i<64; i++)
1103 {
1104 if(_rembBitrate <= ((WebRtc_UWord32)262143 << i))
1105 {
1106 brExp = i;
1107 break;
1108 }
1109 }
1110 const WebRtc_UWord32 brMantissa = (_rembBitrate >> brExp);
1111 rtcpbuffer[pos++]=(WebRtc_UWord8)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1112 rtcpbuffer[pos++]=(WebRtc_UWord8)(brMantissa >> 8);
1113 rtcpbuffer[pos++]=(WebRtc_UWord8)(brMantissa);
1114
1115 for (int i = 0; i < _lengthRembSSRC; i++)
1116 {
1117 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1118 pos += 4;
1119 }
edjee@google.com79b02892013-04-04 19:43:34 +00001120 TRACE_COUNTER1("webrtc_rtcp", "Remb", _rembBitrate);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001121 return 0;
1122}
1123
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001124void
1125RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001126{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001127 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001128 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001129}
1130
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001131WebRtc_Word32
1132RTCPSender::BuildTMMBR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001133{
1134 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1135 // If the sender is an owner of the TMMBN -> send TMMBR
1136 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1137
niklase@google.com470e71d2011-07-07 08:21:25 +00001138 // get current bounding set from RTCP receiver
1139 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001140 // store in candidateSet, allocates one extra slot
1141 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001142
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001143 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1144 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1145 // since RTCPreceiver is not doing the reverse we should be fine
1146 WebRtc_Word32 lengthOfBoundingSet
1147 = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001148
1149 if(lengthOfBoundingSet > 0)
1150 {
1151 for (WebRtc_Word32 i = 0; i < lengthOfBoundingSet; i++)
1152 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001153 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1154 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001155 {
1156 // do not send the same tuple
1157 return 0;
1158 }
1159 }
1160 if(!tmmbrOwner)
1161 {
1162 // use received bounding set as candidate set
1163 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001164 candidateSet->SetEntry(lengthOfBoundingSet,
1165 _tmmbr_Send,
1166 _packetOH_Send,
1167 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001168 int numCandidates = lengthOfBoundingSet+ 1;
1169
1170 // find bounding set
1171 TMMBRSet* boundingSet = NULL;
1172 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1173 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1174 {
1175 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1176 }
1177 if(!tmmbrOwner)
1178 {
1179 // did not enter bounding set, no meaning to send this request
1180 return 0;
1181 }
1182 }
1183 }
1184
1185 if(_tmmbr_Send)
1186 {
1187 // sanity
1188 if(pos + 20 >= IP_PACKET_SIZE)
1189 {
1190 return -2;
1191 }
1192 // add TMMBR indicator
1193 WebRtc_UWord8 FMT = 3;
1194 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1195 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1196
1197 //Length of 4
1198 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1199 rtcpbuffer[pos++]=(WebRtc_UWord8)(4);
1200
1201 // Add our own SSRC
1202 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1203 pos += 4;
1204
1205 // RFC 5104 4.2.1.2. Semantics
1206
1207 // SSRC of media source
1208 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1209 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1210 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1211 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1212
1213 // Additional Feedback Control Information (FCI)
1214 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1215 pos += 4;
1216
1217 WebRtc_UWord32 bitRate = _tmmbr_Send*1000;
1218 WebRtc_UWord32 mmbrExp = 0;
1219 for(WebRtc_UWord32 i=0;i<64;i++)
1220 {
1221 if(bitRate <= ((WebRtc_UWord32)131071 << i))
1222 {
1223 mmbrExp = i;
1224 break;
1225 }
1226 }
1227 WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp);
1228
1229 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1230 rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);
1231 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1232 rtcpbuffer[pos++]=(WebRtc_UWord8)(_packetOH_Send);
1233 }
1234 return 0;
1235}
1236
1237WebRtc_Word32
1238RTCPSender::BuildTMMBN(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1239{
1240 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1241 if(boundingSet == NULL)
1242 {
1243 return -1;
1244 }
1245 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001246 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001247 {
1248 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1249 return -2;
1250 }
1251 WebRtc_UWord8 FMT = 4;
1252 // add TMMBN indicator
1253 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1254 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1255
1256 //Add length later
1257 int posLength = pos;
1258 pos++;
1259 pos++;
1260
1261 // Add our own SSRC
1262 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1263 pos += 4;
1264
1265 // RFC 5104 4.2.2.2. Semantics
1266
1267 // SSRC of media source
1268 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1269 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1270 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1271 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1272
1273 // Additional Feedback Control Information (FCI)
1274 int numBoundingSet = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001275 for(WebRtc_UWord32 n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001276 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001277 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001278 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001279 WebRtc_UWord32 tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001280 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1281 pos += 4;
1282
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001283 WebRtc_UWord32 bitRate = boundingSet->Tmmbr(n) * 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001284 WebRtc_UWord32 mmbrExp = 0;
1285 for(int i=0; i<64; i++)
1286 {
1287 if(bitRate <= ((WebRtc_UWord32)131071 << i))
1288 {
1289 mmbrExp = i;
1290 break;
1291 }
1292 }
1293 WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp);
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001294 WebRtc_UWord32 measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001295
1296 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1297 rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);
1298 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1299 rtcpbuffer[pos++]=(WebRtc_UWord8)(measuredOH);
1300 numBoundingSet++;
1301 }
1302 }
1303 WebRtc_UWord16 length= (WebRtc_UWord16)(2+2*numBoundingSet);
1304 rtcpbuffer[posLength++]=(WebRtc_UWord8)(length>>8);
1305 rtcpbuffer[posLength]=(WebRtc_UWord8)(length);
1306 return 0;
1307}
1308
1309WebRtc_Word32
1310RTCPSender::BuildAPP(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1311{
1312 // sanity
1313 if(_appData == NULL)
1314 {
1315 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1316 return -1;
1317 }
1318 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1319 {
1320 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1321 return -2;
1322 }
1323 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + _appSubType;
1324
1325 // Add APP ID
1326 rtcpbuffer[pos++]=(WebRtc_UWord8)204;
1327
1328 WebRtc_UWord16 length = (_appLength>>2) + 2; // include SSRC and name
1329 rtcpbuffer[pos++]=(WebRtc_UWord8)(length>>8);
1330 rtcpbuffer[pos++]=(WebRtc_UWord8)(length);
1331
1332 // Add our own SSRC
1333 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1334 pos += 4;
1335
1336 // Add our application name
1337 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1338 pos += 4;
1339
1340 // Add the data
1341 memcpy(rtcpbuffer +pos, _appData,_appLength);
1342 pos += _appLength;
1343 return 0;
1344}
1345
1346WebRtc_Word32
1347RTCPSender::BuildNACK(WebRtc_UWord8* rtcpbuffer,
1348 WebRtc_UWord32& pos,
1349 const WebRtc_Word32 nackSize,
edjee@google.com79b02892013-04-04 19:43:34 +00001350 const WebRtc_UWord16* nackList,
1351 std::string* nackString)
niklase@google.com470e71d2011-07-07 08:21:25 +00001352{
1353 // sanity
1354 if(pos + 16 >= IP_PACKET_SIZE)
1355 {
1356 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1357 return -2;
1358 }
1359
1360 // int size, WebRtc_UWord16* nackList
1361 // add nack list
1362 WebRtc_UWord8 FMT = 1;
1363 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1364 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1365
1366 rtcpbuffer[pos++]=(WebRtc_UWord8) 0;
1367 int nackSizePos = pos;
1368 rtcpbuffer[pos++]=(WebRtc_UWord8)(3); //setting it to one kNACK signal as default
1369
1370 // Add our own SSRC
1371 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1372 pos += 4;
1373
1374 // Add the remote SSRC
1375 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1376 pos += 4;
1377
1378 // add the list
1379 int i = 0;
1380 int numOfNackFields = 0;
edjee@google.com79b02892013-04-04 19:43:34 +00001381 NACKStringBuilder stringBuilder;
stefan@webrtc.orga2710702013-03-05 09:02:06 +00001382 while (nackSize > i && numOfNackFields < kRtcpMaxNackFields)
niklase@google.com470e71d2011-07-07 08:21:25 +00001383 {
1384 WebRtc_UWord16 nack = nackList[i];
1385 // put dow our sequence number
1386 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, nack);
1387 pos += 2;
edjee@google.com79b02892013-04-04 19:43:34 +00001388 stringBuilder.PushNACK(nack);
niklase@google.com470e71d2011-07-07 08:21:25 +00001389
1390 i++;
1391 numOfNackFields++;
1392 if(nackSize > i)
1393 {
1394 bool moreThan16Away = (WebRtc_UWord16(nack+16) < nackList[i])?true: false;
1395 if(!moreThan16Away)
1396 {
1397 // check for a wrap
1398 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1399 {
1400 // wrap
1401 moreThan16Away = true;
1402 }
1403 }
1404 if(moreThan16Away)
1405 {
1406 // next is more than 16 away
1407 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1408 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1409 } else
1410 {
1411 // build our bitmask
1412 WebRtc_UWord16 bitmask = 0;
1413
1414 bool within16Away = (WebRtc_UWord16(nack+16) > nackList[i])?true: false;
1415 if(within16Away)
1416 {
1417 // check for a wrap
1418 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1419 {
1420 // wrap
1421 within16Away = false;
1422 }
1423 }
1424
1425 while( nackSize > i && within16Away)
1426 {
1427 WebRtc_Word16 shift = (nackList[i]-nack)-1;
1428 assert(!(shift > 15) && !(shift < 0));
1429
1430 bitmask += (1<< shift);
edjee@google.com79b02892013-04-04 19:43:34 +00001431 stringBuilder.PushNACK(nackList[i]);
niklase@google.com470e71d2011-07-07 08:21:25 +00001432 i++;
1433 if(nackSize > i)
1434 {
1435 within16Away = (WebRtc_UWord16(nack+16) > nackList[i])?true: false;
1436 if(within16Away)
1437 {
1438 // check for a wrap
1439 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1440 {
1441 // wrap
1442 within16Away = false;
1443 }
1444 }
1445 }
1446 }
1447 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, bitmask);
1448 pos += 2;
1449 }
1450 // sanity do we have room from one more 4 byte block?
1451 if(pos + 4 >= IP_PACKET_SIZE)
1452 {
1453 return -2;
1454 }
1455 } else
1456 {
1457 // no more in the list
1458 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1459 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1460 }
1461 }
1462 rtcpbuffer[nackSizePos]=(WebRtc_UWord8)(2+numOfNackFields);
edjee@google.com79b02892013-04-04 19:43:34 +00001463 *nackString = stringBuilder.GetResult();
niklase@google.com470e71d2011-07-07 08:21:25 +00001464 return 0;
1465}
1466
1467WebRtc_Word32
1468RTCPSender::BuildBYE(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1469{
1470 // sanity
1471 if(pos + 8 >= IP_PACKET_SIZE)
1472 {
1473 return -2;
1474 }
1475 if(_includeCSRCs)
1476 {
1477 // Add a bye packet
1478 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1479 rtcpbuffer[pos++]=(WebRtc_UWord8)203;
1480
1481 // length
1482 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1483 rtcpbuffer[pos++]=(WebRtc_UWord8)(1 + _CSRCs);
1484
1485 // Add our own SSRC
1486 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1487 pos += 4;
1488
1489 // add CSRCs
1490 for(int i = 0; i < _CSRCs; i++)
1491 {
1492 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1493 pos += 4;
1494 }
1495 } else
1496 {
1497 // Add a bye packet
1498 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1; // number of SSRC+CSRCs
1499 rtcpbuffer[pos++]=(WebRtc_UWord8)203;
1500
1501 // length
1502 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1503 rtcpbuffer[pos++]=(WebRtc_UWord8)1;
1504
1505 // Add our own SSRC
1506 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1507 pos += 4;
1508 }
1509 return 0;
1510}
1511
1512WebRtc_Word32
1513RTCPSender::BuildVoIPMetric(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1514{
1515 // sanity
1516 if(pos + 44 >= IP_PACKET_SIZE)
1517 {
1518 return -2;
1519 }
1520
1521 // Add XR header
1522 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
1523 rtcpbuffer[pos++]=(WebRtc_UWord8)207;
1524
1525 WebRtc_UWord32 XRLengthPos = pos;
1526
1527 // handle length later on
1528 pos++;
1529 pos++;
1530
1531 // Add our own SSRC
1532 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1533 pos += 4;
1534
1535 // Add a VoIP metrics block
1536 rtcpbuffer[pos++]=7;
1537 rtcpbuffer[pos++]=0;
1538 rtcpbuffer[pos++]=0;
1539 rtcpbuffer[pos++]=8;
1540
1541 // Add the remote SSRC
1542 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1543 pos += 4;
1544
1545 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1546 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1547 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1548 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1549
1550 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.burstDuration >> 8);
1551 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.burstDuration);
1552 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.gapDuration >> 8);
1553 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.gapDuration);
1554
1555 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.roundTripDelay >> 8);
1556 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.roundTripDelay);
1557 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.endSystemDelay >> 8);
1558 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.endSystemDelay);
1559
1560 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1561 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1562 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1563 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1564
1565 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1566 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1567 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1568 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1569
1570 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1571 rtcpbuffer[pos++] = 0; // reserved
1572 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBnominal >> 8);
1573 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBnominal);
1574
1575 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBmax >> 8);
1576 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBmax);
1577 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBabsMax >> 8);
1578 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBabsMax);
1579
1580 rtcpbuffer[XRLengthPos]=(WebRtc_UWord8)(0);
1581 rtcpbuffer[XRLengthPos+1]=(WebRtc_UWord8)(10);
1582 return 0;
1583}
1584
1585WebRtc_Word32
1586RTCPSender::SendRTCP(const WebRtc_UWord32 packetTypeFlags,
1587 const WebRtc_Word32 nackSize, // NACK
1588 const WebRtc_UWord16* nackList, // NACK
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001589 const bool repeat, // FIR
niklase@google.com470e71d2011-07-07 08:21:25 +00001590 const WebRtc_UWord64 pictureID) // SLI & RPSI
1591{
1592 WebRtc_UWord32 rtcpPacketTypeFlags = packetTypeFlags;
1593 WebRtc_UWord32 pos = 0;
1594 WebRtc_UWord8 rtcpbuffer[IP_PACKET_SIZE];
1595
niklase@google.com470e71d2011-07-07 08:21:25 +00001596 do // only to be able to use break :) (and the critsect must be inside its own scope)
1597 {
1598 // collect the received information
1599 RTCPReportBlock received;
1600 bool hasReceived = false;
1601 WebRtc_UWord32 NTPsec = 0;
1602 WebRtc_UWord32 NTPfrac = 0;
xians@webrtc.org8738d272011-11-25 13:43:53 +00001603 bool rtcpCompound = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001604 WebRtc_UWord32 jitterTransmissionOffset = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001605
xians@webrtc.org8738d272011-11-25 13:43:53 +00001606 {
1607 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1608 if(_method == kRtcpOff)
1609 {
1610 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1611 "%s invalid state", __FUNCTION__);
1612 return -1;
1613 }
1614 rtcpCompound = (_method == kRtcpCompound) ? true : false;
1615 }
1616
1617 if (rtcpCompound ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001618 rtcpPacketTypeFlags & kRtcpReport ||
1619 rtcpPacketTypeFlags & kRtcpSr ||
1620 rtcpPacketTypeFlags & kRtcpRr)
1621 {
1622 // get statistics from our RTPreceiver outside critsect
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001623 if(_rtpRtcp.ReportBlockStatistics(&received.fractionLost,
1624 &received.cumulativeLost,
1625 &received.extendedHighSeqNum,
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001626 &received.jitter,
1627 &jitterTransmissionOffset) == 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001628 {
1629 hasReceived = true;
1630
1631 WebRtc_UWord32 lastReceivedRRNTPsecs = 0;
1632 WebRtc_UWord32 lastReceivedRRNTPfrac = 0;
1633 WebRtc_UWord32 remoteSR = 0;
1634
1635 // ok even if we have not received a SR, we will send 0 in that case
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001636 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1637 lastReceivedRRNTPfrac,
1638 remoteSR);
niklase@google.com470e71d2011-07-07 08:21:25 +00001639
1640 // get our NTP as late as possible to avoid a race
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001641 _clock->CurrentNtp(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001642
1643 // Delay since last received report
1644 WebRtc_UWord32 delaySinceLastReceivedSR = 0;
1645 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
1646 {
1647 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1648 WebRtc_UWord32 now=NTPsec&0x0000FFFF;
1649 now <<=16;
1650 now += (NTPfrac&0xffff0000)>>16;
1651
1652 WebRtc_UWord32 receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
1653 receiveTime <<=16;
1654 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1655
1656 delaySinceLastReceivedSR = now-receiveTime;
1657 }
1658 received.delaySinceLastSR = delaySinceLastReceivedSR;
1659 received.lastSR = remoteSR;
1660 } else
1661 {
1662 // we need to send our NTP even if we dont have received any reports
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001663 _clock->CurrentNtp(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001664 }
1665 }
1666
1667 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1668
1669 if(_TMMBR ) // attach TMMBR to send and receive reports
1670 {
1671 rtcpPacketTypeFlags |= kRtcpTmmbr;
1672 }
1673 if(_appSend)
1674 {
1675 rtcpPacketTypeFlags |= kRtcpApp;
1676 _appSend = false;
1677 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001678 if(_REMB && _sendREMB)
1679 {
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +00001680 // Always attach REMB to SR if that is configured. Note that REMB is
1681 // only sent on one of the RTP modules in the REMB group.
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001682 rtcpPacketTypeFlags |= kRtcpRemb;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001683 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001684 if(_xrSendVoIPMetric)
1685 {
1686 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1687 _xrSendVoIPMetric = false;
1688 }
1689 if(_sendTMMBN) // set when having received a TMMBR
1690 {
1691 rtcpPacketTypeFlags |= kRtcpTmmbn;
1692 _sendTMMBN = false;
1693 }
1694
1695 if(_method == kRtcpCompound)
1696 {
1697 if(_sending)
1698 {
1699 rtcpPacketTypeFlags |= kRtcpSr;
1700 } else
1701 {
1702 rtcpPacketTypeFlags |= kRtcpRr;
1703 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001704 if (_IJ && hasReceived)
1705 {
1706 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1707 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001708 } else if(_method == kRtcpNonCompound)
1709 {
1710 if(rtcpPacketTypeFlags & kRtcpReport)
1711 {
1712 if(_sending)
1713 {
1714 rtcpPacketTypeFlags |= kRtcpSr;
1715 } else
1716 {
1717 rtcpPacketTypeFlags |= kRtcpRr;
1718 }
1719 }
1720 }
1721 if( rtcpPacketTypeFlags & kRtcpRr ||
1722 rtcpPacketTypeFlags & kRtcpSr)
1723 {
1724 // generate next time to send a RTCP report
1725 // seeded from RTP constructor
1726 WebRtc_Word32 random = rand() % 1000;
1727 WebRtc_Word32 timeToNext = RTCP_INTERVAL_AUDIO_MS;
1728
1729 if(_audio)
1730 {
1731 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
1732 }else
1733 {
1734 WebRtc_UWord32 minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1735 if(_sending)
1736 {
1737 // calc bw for video 360/sendBW in kbit/s
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001738 WebRtc_UWord32 sendBitrateKbit = 0;
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001739 WebRtc_UWord32 videoRate = 0;
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001740 WebRtc_UWord32 fecRate = 0;
1741 WebRtc_UWord32 nackRate = 0;
1742 _rtpRtcp.BitrateSent(&sendBitrateKbit,
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001743 &videoRate,
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001744 &fecRate,
1745 &nackRate);
1746 sendBitrateKbit /= 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001747 if(sendBitrateKbit != 0)
1748 {
1749 minIntervalMs = 360000/sendBitrateKbit;
1750 }
1751 }
1752 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1753 {
1754 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1755 }
1756 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1757 }
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001758 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
niklase@google.com470e71d2011-07-07 08:21:25 +00001759 }
1760
1761 // if the data does not fitt in the packet we fill it as much as possible
1762 WebRtc_Word32 buildVal = 0;
1763
1764 if(rtcpPacketTypeFlags & kRtcpSr)
1765 {
1766 if(hasReceived)
1767 {
1768 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
1769 } else
1770 {
1771 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac);
1772 }
1773 if(buildVal == -1)
1774 {
1775 return -1; // error
1776
1777 }else if(buildVal == -2)
1778 {
1779 break; // out of buffer
1780 }
1781 buildVal = BuildSDEC(rtcpbuffer, pos);
1782 if(buildVal == -1)
1783 {
1784 return -1; // error
1785
1786 }else if(buildVal == -2)
1787 {
1788 break; // out of buffer
1789 }
1790
1791 }else if(rtcpPacketTypeFlags & kRtcpRr)
1792 {
1793 if(hasReceived)
1794 {
1795 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
1796 }else
1797 {
1798 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
1799 }
1800 if(buildVal == -1)
1801 {
1802 return -1; // error
1803
1804 }else if(buildVal == -2)
1805 {
1806 break; // out of buffer
1807 }
1808 // only of set
1809 if(_CNAME[0] != 0)
1810 {
1811 buildVal = BuildSDEC(rtcpbuffer, pos);
1812 if(buildVal == -1)
1813 {
1814 return -1; // error
1815 }
1816 }
1817 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001818 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1819 {
1820 // If present, this RTCP packet must be placed after a
1821 // receiver report.
1822 buildVal = BuildExtendedJitterReport(rtcpbuffer,
1823 pos,
1824 jitterTransmissionOffset);
1825 if(buildVal == -1)
1826 {
1827 return -1; // error
1828 }
1829 else if(buildVal == -2)
1830 {
1831 break; // out of buffer
1832 }
1833 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001834 if(rtcpPacketTypeFlags & kRtcpPli)
1835 {
1836 buildVal = BuildPLI(rtcpbuffer, pos);
1837 if(buildVal == -1)
1838 {
1839 return -1; // error
1840
1841 }else if(buildVal == -2)
1842 {
1843 break; // out of buffer
1844 }
edjee@google.com79b02892013-04-04 19:43:34 +00001845 TRACE_EVENT_INSTANT1("webrtc_rtcp", "SendRTCP", "type", "pli");
1846 _pliCount++;
1847 TRACE_COUNTER1("webrtc_rtcp", "PLI Count", _pliCount);
niklase@google.com470e71d2011-07-07 08:21:25 +00001848 }
1849 if(rtcpPacketTypeFlags & kRtcpFir)
1850 {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001851 buildVal = BuildFIR(rtcpbuffer, pos, repeat);
niklase@google.com470e71d2011-07-07 08:21:25 +00001852 if(buildVal == -1)
1853 {
1854 return -1; // error
1855
1856 }else if(buildVal == -2)
1857 {
1858 break; // out of buffer
1859 }
edjee@google.com79b02892013-04-04 19:43:34 +00001860 TRACE_EVENT_INSTANT1("webrtc_rtcp", "SendRTCP", "type", "fir");
1861 _fullIntraRequestCount++;
1862 TRACE_COUNTER1("webrtc_rtcp", "FIR Count", _fullIntraRequestCount);
niklase@google.com470e71d2011-07-07 08:21:25 +00001863 }
1864 if(rtcpPacketTypeFlags & kRtcpSli)
1865 {
1866 buildVal = BuildSLI(rtcpbuffer, pos, (WebRtc_UWord8)pictureID);
1867 if(buildVal == -1)
1868 {
1869 return -1; // error
1870
1871 }else if(buildVal == -2)
1872 {
1873 break; // out of buffer
1874 }
1875 }
1876 if(rtcpPacketTypeFlags & kRtcpRpsi)
1877 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001878 const WebRtc_Word8 payloadType = _rtpRtcp.SendPayloadType();
niklase@google.com470e71d2011-07-07 08:21:25 +00001879 if(payloadType == -1)
1880 {
1881 return -1;
1882 }
1883 buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (WebRtc_UWord8)payloadType);
1884 if(buildVal == -1)
1885 {
1886 return -1; // error
1887
1888 }else if(buildVal == -2)
1889 {
1890 break; // out of buffer
1891 }
1892 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001893 if(rtcpPacketTypeFlags & kRtcpRemb)
1894 {
1895 buildVal = BuildREMB(rtcpbuffer, pos);
1896 if(buildVal == -1)
1897 {
1898 return -1; // error
1899
1900 }else if(buildVal == -2)
1901 {
1902 break; // out of buffer
1903 }
edjee@google.com79b02892013-04-04 19:43:34 +00001904 TRACE_EVENT_INSTANT2("webrtc_rtcp", "SendRTCP", "type", "remb",
1905 "bitrate", _rembBitrate);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001906 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001907 if(rtcpPacketTypeFlags & kRtcpBye)
1908 {
1909 buildVal = BuildBYE(rtcpbuffer, pos);
1910 if(buildVal == -1)
1911 {
1912 return -1; // error
1913
1914 }else if(buildVal == -2)
1915 {
1916 break; // out of buffer
1917 }
1918 }
1919 if(rtcpPacketTypeFlags & kRtcpApp)
1920 {
1921 buildVal = BuildAPP(rtcpbuffer, pos);
1922 if(buildVal == -1)
1923 {
1924 return -1; // error
1925
1926 }else if(buildVal == -2)
1927 {
1928 break; // out of buffer
1929 }
1930 }
1931 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1932 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001933 buildVal = BuildTMMBR(rtcpbuffer, pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001934 if(buildVal == -1)
1935 {
1936 return -1; // error
1937
1938 }else if(buildVal == -2)
1939 {
1940 break; // out of buffer
1941 }
1942 }
1943 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1944 {
1945 buildVal = BuildTMMBN(rtcpbuffer, pos);
1946 if(buildVal == -1)
1947 {
1948 return -1; // error
1949
1950 }else if(buildVal == -2)
1951 {
1952 break; // out of buffer
1953 }
1954 }
1955 if(rtcpPacketTypeFlags & kRtcpNack)
1956 {
edjee@google.com79b02892013-04-04 19:43:34 +00001957 std::string nackString;
1958 buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList,
1959 &nackString);
niklase@google.com470e71d2011-07-07 08:21:25 +00001960 if(buildVal == -1)
1961 {
1962 return -1; // error
1963
1964 }else if(buildVal == -2)
1965 {
1966 break; // out of buffer
1967 }
edjee@google.com79b02892013-04-04 19:43:34 +00001968 TRACE_EVENT_INSTANT2("webrtc_rtcp", "SendRTCP", "type", "nack",
1969 "list", TRACE_STR_COPY(nackString.c_str()));
1970 _nackCount++;
1971 TRACE_COUNTER1("webrtc_rtcp", "Nacks", _nackCount);
niklase@google.com470e71d2011-07-07 08:21:25 +00001972 }
1973 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1974 {
1975 buildVal = BuildVoIPMetric(rtcpbuffer, pos);
1976 if(buildVal == -1)
1977 {
1978 return -1; // error
1979
1980 }else if(buildVal == -2)
1981 {
1982 break; // out of buffer
1983 }
1984 }
1985 }while (false);
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001986 // Sanity don't send empty packets.
1987 if (pos == 0)
1988 {
1989 return -1;
1990 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001991 return SendToNetwork(rtcpbuffer, (WebRtc_UWord16)pos);
1992}
1993
1994WebRtc_Word32
1995RTCPSender::SendToNetwork(const WebRtc_UWord8* dataBuffer,
1996 const WebRtc_UWord16 length)
1997{
1998 CriticalSectionScoped lock(_criticalSectionTransport);
1999 if(_cbTransport)
2000 {
2001 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
2002 {
2003 return 0;
2004 }
2005 }
2006 return -1;
2007}
2008
2009WebRtc_Word32
2010RTCPSender::SetCSRCStatus(const bool include)
2011{
2012 _includeCSRCs = include;
2013 return 0;
2014}
2015
2016WebRtc_Word32
2017RTCPSender::SetCSRCs(const WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize],
2018 const WebRtc_UWord8 arrLength)
2019{
2020 if(arrLength > kRtpCsrcSize)
2021 {
2022 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2023 assert(false);
2024 return -1;
2025 }
2026
2027 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2028
2029 for(int i = 0; i < arrLength;i++)
2030 {
2031 _CSRC[i] = arrOfCSRC[i];
2032 }
2033 _CSRCs = arrLength;
2034 return 0;
2035}
2036
2037WebRtc_Word32
2038RTCPSender::SetApplicationSpecificData(const WebRtc_UWord8 subType,
2039 const WebRtc_UWord32 name,
2040 const WebRtc_UWord8* data,
2041 const WebRtc_UWord16 length)
2042{
2043 if(length %4 != 0)
2044 {
2045 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2046 return -1;
2047 }
2048 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2049
2050 if(_appData)
2051 {
2052 delete [] _appData;
2053 }
2054
2055 _appSend = true;
2056 _appSubType = subType;
2057 _appName = name;
2058 _appData = new WebRtc_UWord8[length];
2059 _appLength = length;
2060 memcpy(_appData, data, length);
2061 return 0;
2062}
2063
2064WebRtc_Word32
2065RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2066{
2067 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2068 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2069
2070 _xrSendVoIPMetric = true;
2071 return 0;
2072}
2073
2074// called under critsect _criticalSectionRTCPSender
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002075WebRtc_Word32 RTCPSender::AddReportBlocks(WebRtc_UWord8* rtcpbuffer,
2076 WebRtc_UWord32& pos,
2077 WebRtc_UWord8& numberOfReportBlocks,
2078 const RTCPReportBlock* received,
2079 const WebRtc_UWord32 NTPsec,
2080 const WebRtc_UWord32 NTPfrac) {
2081 // sanity one block
2082 if(pos + 24 >= IP_PACKET_SIZE) {
2083 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2084 "%s invalid argument", __FUNCTION__);
2085 return -1;
2086 }
2087 numberOfReportBlocks = _reportBlocks.size();
2088 if (received) {
2089 // add our multiple RR to numberOfReportBlocks
2090 numberOfReportBlocks++;
2091 }
2092 if (received) {
2093 // answer to the one that sends to me
2094 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac);
2095
2096 // Remote SSRC
2097 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
2098 pos += 4;
2099
2100 // fraction lost
2101 rtcpbuffer[pos++]=received->fractionLost;
2102
2103 // cumulative loss
2104 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2105 received->cumulativeLost);
2106 pos += 3;
2107 // extended highest seq_no, contain the highest sequence number received
2108 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2109 received->extendedHighSeqNum);
2110 pos += 4;
2111
2112 //Jitter
2113 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
2114 pos += 4;
2115
2116 // Last SR timestamp, our NTP time when we received the last report
2117 // This is the value that we read from the send report packet not when we
2118 // received it...
2119 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
2120 pos += 4;
2121
2122 // Delay since last received report,time since we received the report
2123 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2124 received->delaySinceLastSR);
2125 pos += 4;
2126 }
2127 if ((pos + _reportBlocks.size() * 24) >= IP_PACKET_SIZE) {
2128 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2129 "%s invalid argument", __FUNCTION__);
2130 return -1;
2131 }
2132 std::map<WebRtc_UWord32, RTCPReportBlock*>::iterator it =
2133 _reportBlocks.begin();
2134
2135 for (; it != _reportBlocks.end(); it++) {
2136 // we can have multiple report block in a conference
2137 WebRtc_UWord32 remoteSSRC = it->first;
2138 RTCPReportBlock* reportBlock = it->second;
2139 if (reportBlock) {
2140 // Remote SSRC
2141 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
2142 pos += 4;
2143
2144 // fraction lost
2145 rtcpbuffer[pos++] = reportBlock->fractionLost;
2146
2147 // cumulative loss
2148 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2149 reportBlock->cumulativeLost);
2150 pos += 3;
2151
2152 // extended highest seq_no, contain the highest sequence number received
2153 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2154 reportBlock->extendedHighSeqNum);
2155 pos += 4;
2156
2157 //Jitter
2158 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2159 reportBlock->jitter);
2160 pos += 4;
2161
2162 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2163 reportBlock->lastSR);
2164 pos += 4;
2165
2166 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2167 reportBlock->delaySinceLastSR);
2168 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002169 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002170 }
2171 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00002172}
2173
2174// no callbacks allowed inside this function
2175WebRtc_Word32
2176RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
2177 const WebRtc_UWord32 maxBitrateKbit)
2178{
2179 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2180
2181 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2182 {
2183 _sendTMMBN = true;
2184 return 0;
2185 }
2186 return -1;
2187}
niklase@google.com470e71d2011-07-07 08:21:25 +00002188} // namespace webrtc