blob: 051fc448c335484ce58819c53765fc497715746f [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"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000021
niklase@google.com470e71d2011-07-07 08:21:25 +000022namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000023
24using RTCPUtility::RTCPCnameInformation;
25
niklase@google.com470e71d2011-07-07 08:21:25 +000026RTCPSender::RTCPSender(const WebRtc_Word32 id,
27 const bool audio,
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000028 RtpRtcpClock* clock,
pwestin@webrtc.org741da942011-09-20 13:52:04 +000029 ModuleRtpRtcpImpl* owner) :
niklase@google.com470e71d2011-07-07 08:21:25 +000030 _id(id),
31 _audio(audio),
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000032 _clock(*clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000033 _method(kRtcpOff),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000034 _rtpRtcp(*owner),
henrike@webrtc.org65573f22011-12-13 19:17:27 +000035 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000036 _cbTransport(NULL),
37
henrike@webrtc.org65573f22011-12-13 19:17:27 +000038 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000039 _usingNack(false),
40 _sending(false),
41 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000042 _REMB(false),
43 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000044 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +000045 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000046 _nextTimeToSendRTCP(0),
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000047 start_timestamp_(0),
48 last_rtp_timestamp_(0),
49 last_frame_capture_time_ms_(-1),
niklase@google.com470e71d2011-07-07 08:21:25 +000050 _SSRC(0),
51 _remoteSSRC(0),
52 _CNAME(),
53 _reportBlocks(),
54 _csrcCNAMEs(),
55
56 _cameraDelayMS(0),
57
58 _lastSendReport(),
59 _lastRTCPTime(),
60
61 _CSRCs(0),
62 _CSRC(),
63 _includeCSRCs(true),
64
65 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000066
pwestin@webrtc.org741da942011-09-20 13:52:04 +000067 _lengthRembSSRC(0),
68 _sizeRembSSRC(0),
69 _rembSSRC(NULL),
70 _rembBitrate(0),
71
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000072 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +000073 _tmmbr_Send(0),
74 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000075
76 _appSend(false),
77 _appSubType(0),
78 _appName(),
79 _appData(NULL),
80 _appLength(0),
81 _xrSendVoIPMetric(false),
82 _xrVoIPMetric()
83{
84 memset(_CNAME, 0, sizeof(_CNAME));
85 memset(_lastSendReport, 0, sizeof(_lastSendReport));
86 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
87
88 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
89}
90
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000091RTCPSender::~RTCPSender() {
92 delete [] _rembSSRC;
93 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +000094
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000095 while (!_reportBlocks.empty()) {
96 std::map<WebRtc_UWord32, RTCPReportBlock*>::iterator it =
97 _reportBlocks.begin();
98 delete it->second;
99 _reportBlocks.erase(it);
100 }
101 while (!_csrcCNAMEs.empty()) {
102 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator it =
103 _csrcCNAMEs.begin();
104 delete it->second;
105 _csrcCNAMEs.erase(it);
106 }
107 delete _criticalSectionTransport;
108 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000109
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000110 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000111}
112
113WebRtc_Word32
114RTCPSender::Init()
115{
116 CriticalSectionScoped lock(_criticalSectionRTCPSender);
117
118 _method = kRtcpOff;
119 _cbTransport = NULL;
120 _usingNack = false;
121 _sending = false;
122 _sendTMMBN = false;
123 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000124 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000125 _REMB = false;
126 _sendREMB = false;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000127 last_rtp_timestamp_ = 0;
128 last_frame_capture_time_ms_ = -1;
129 start_timestamp_ = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000130 _SSRC = 0;
131 _remoteSSRC = 0;
132 _cameraDelayMS = 0;
133 _sequenceNumberFIR = 0;
134 _tmmbr_Send = 0;
135 _packetOH_Send = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000136 _nextTimeToSendRTCP = 0;
137 _CSRCs = 0;
138 _appSend = false;
139 _appSubType = 0;
140
141 if(_appData)
142 {
143 delete [] _appData;
144 _appData = NULL;
145 }
146 _appLength = 0;
147
148 _xrSendVoIPMetric = false;
149
150 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
151 memset(_CNAME, 0, sizeof(_CNAME));
152 memset(_lastSendReport, 0, sizeof(_lastSendReport));
153 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
154 return 0;
155}
156
157void
158RTCPSender::ChangeUniqueId(const WebRtc_Word32 id)
159{
160 _id = id;
161}
162
163WebRtc_Word32
164RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
165{
166 CriticalSectionScoped lock(_criticalSectionTransport);
167 _cbTransport = outgoingTransport;
168 return 0;
169}
170
171RTCPMethod
172RTCPSender::Status() const
173{
174 CriticalSectionScoped lock(_criticalSectionRTCPSender);
175 return _method;
176}
177
178WebRtc_Word32
179RTCPSender::SetRTCPStatus(const RTCPMethod method)
180{
181 CriticalSectionScoped lock(_criticalSectionRTCPSender);
182 if(method != kRtcpOff)
183 {
184 if(_audio)
185 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000186 _nextTimeToSendRTCP = _clock.GetTimeInMS() + (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000187 } else
188 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000189 _nextTimeToSendRTCP = _clock.GetTimeInMS() + (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000190 }
191 }
192 _method = method;
193 return 0;
194}
195
196bool
197RTCPSender::Sending() const
198{
199 CriticalSectionScoped lock(_criticalSectionRTCPSender);
200 return _sending;
201}
202
203WebRtc_Word32
204RTCPSender::SetSendingStatus(const bool sending)
205{
206 bool sendRTCPBye = false;
207 {
208 CriticalSectionScoped lock(_criticalSectionRTCPSender);
209
210 if(_method != kRtcpOff)
211 {
212 if(sending == false && _sending == true)
213 {
214 // Trigger RTCP bye
215 sendRTCPBye = true;
216 }
217 }
218 _sending = sending;
219 }
220 if(sendRTCPBye)
221 {
222 return SendRTCP(kRtcpBye);
223 }
224 return 0;
225}
226
227bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000228RTCPSender::REMB() const
229{
230 CriticalSectionScoped lock(_criticalSectionRTCPSender);
231 return _REMB;
232}
233
234WebRtc_Word32
235RTCPSender::SetREMBStatus(const bool enable)
236{
237 CriticalSectionScoped lock(_criticalSectionRTCPSender);
238 _REMB = enable;
239 return 0;
240}
241
242WebRtc_Word32
243RTCPSender::SetREMBData(const WebRtc_UWord32 bitrate,
244 const WebRtc_UWord8 numberOfSSRC,
245 const WebRtc_UWord32* SSRC)
246{
247 CriticalSectionScoped lock(_criticalSectionRTCPSender);
248 _rembBitrate = bitrate;
249
250 if(_sizeRembSSRC < numberOfSSRC)
251 {
252 delete [] _rembSSRC;
253 _rembSSRC = new WebRtc_UWord32[numberOfSSRC];
254 _sizeRembSSRC = numberOfSSRC;
255 }
256
257 _lengthRembSSRC = numberOfSSRC;
258 for (int i = 0; i < numberOfSSRC; i++)
259 {
260 _rembSSRC[i] = SSRC[i];
261 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000262 _sendREMB = true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000263 return 0;
264}
265
266bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000267RTCPSender::TMMBR() const
268{
269 CriticalSectionScoped lock(_criticalSectionRTCPSender);
270 return _TMMBR;
271}
272
273WebRtc_Word32
274RTCPSender::SetTMMBRStatus(const bool enable)
275{
276 CriticalSectionScoped lock(_criticalSectionRTCPSender);
277 _TMMBR = enable;
278 return 0;
279}
280
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000281bool
282RTCPSender::IJ() const
283{
284 CriticalSectionScoped lock(_criticalSectionRTCPSender);
285 return _IJ;
286}
287
288WebRtc_Word32
289RTCPSender::SetIJStatus(const bool enable)
290{
291 CriticalSectionScoped lock(_criticalSectionRTCPSender);
292 _IJ = enable;
293 return 0;
294}
295
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000296void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
297 start_timestamp_ = start_timestamp;
298}
299
300void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
301 int64_t capture_time_ms) {
302 last_rtp_timestamp_ = rtp_timestamp;
303 if (capture_time_ms < 0) {
304 // We don't currently get a capture time from VoiceEngine.
305 last_frame_capture_time_ms_ = _clock.GetTimeInMS();
306 } else {
307 last_frame_capture_time_ms_ = capture_time_ms;
308 }
309}
310
niklase@google.com470e71d2011-07-07 08:21:25 +0000311void
312RTCPSender::SetSSRC( const WebRtc_UWord32 ssrc)
313{
314 CriticalSectionScoped lock(_criticalSectionRTCPSender);
315
316 if(_SSRC != 0)
317 {
318 // not first SetSSRC, probably due to a collision
319 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000320 // make sure that we send a RTP packet
321 _nextTimeToSendRTCP = _clock.GetTimeInMS() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000322 }
323 _SSRC = ssrc;
324}
325
326WebRtc_Word32
327RTCPSender::SetRemoteSSRC( const WebRtc_UWord32 ssrc)
328{
329 CriticalSectionScoped lock(_criticalSectionRTCPSender);
330 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000331 return 0;
332}
333
334WebRtc_Word32
335RTCPSender::SetCameraDelay(const WebRtc_Word32 delayMS)
336{
337 CriticalSectionScoped lock(_criticalSectionRTCPSender);
338 if(delayMS > 1000 || delayMS < -1000)
339 {
340 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
341 return -1;
342 }
343 _cameraDelayMS = delayMS;
344 return 0;
345}
346
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000347WebRtc_Word32 RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
348 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000349 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000350 cName[RTCP_CNAME_SIZE - 1] = 0;
351 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000352 return 0;
353}
354
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000355WebRtc_Word32 RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000356 if (!cName)
357 return -1;
358
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000359 CriticalSectionScoped lock(_criticalSectionRTCPSender);
360 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
361 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
362 return 0;
363}
364
365WebRtc_Word32 RTCPSender::AddMixedCNAME(const WebRtc_UWord32 SSRC,
366 const char cName[RTCP_CNAME_SIZE]) {
367 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000368 CriticalSectionScoped lock(_criticalSectionRTCPSender);
369 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
370 return -1;
371 }
372 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000373 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
374 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000375 _csrcCNAMEs[SSRC] = ptr;
376 return 0;
377}
378
379WebRtc_Word32 RTCPSender::RemoveMixedCNAME(const WebRtc_UWord32 SSRC) {
380 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000381 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator it =
382 _csrcCNAMEs.find(SSRC);
383
384 if (it == _csrcCNAMEs.end()) {
385 return -1;
386 }
387 delete it->second;
388 _csrcCNAMEs.erase(it);
389 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000390}
391
392bool
393RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
394{
395/*
396 For audio we use a fix 5 sec interval
397
398 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
399 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
400
401
402From RFC 3550
403
404 MAX RTCP BW is 5% if the session BW
405 A send report is approximately 65 bytes inc CNAME
406 A report report is approximately 28 bytes
407
408 The RECOMMENDED value for the reduced minimum in seconds is 360
409 divided by the session bandwidth in kilobits/second. This minimum
410 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
411
412 If the participant has not yet sent an RTCP packet (the variable
413 initial is true), the constant Tmin is set to 2.5 seconds, else it
414 is set to 5 seconds.
415
416 The interval between RTCP packets is varied randomly over the
417 range [0.5,1.5] times the calculated interval to avoid unintended
418 synchronization of all participants
419
420 if we send
421 If the participant is a sender (we_sent true), the constant C is
422 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
423 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
424 number of senders.
425
426 if we receive only
427 If we_sent is not true, the constant C is set
428 to the average RTCP packet size divided by 75% of the RTCP
429 bandwidth. The constant n is set to the number of receivers
430 (members - senders). If the number of senders is greater than
431 25%, senders and receivers are treated together.
432
433 reconsideration NOT required for peer-to-peer
434 "timer reconsideration" is
435 employed. This algorithm implements a simple back-off mechanism
436 which causes users to hold back RTCP packet transmission if the
437 group sizes are increasing.
438
439 n = number of members
440 C = avg_size/(rtcpBW/4)
441
442 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
443
444 4. The calculated interval T is set to a number uniformly distributed
445 between 0.5 and 1.5 times the deterministic calculated interval.
446
447 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
448 for the fact that the timer reconsideration algorithm converges to
449 a value of the RTCP bandwidth below the intended average
450*/
451
pwestin@webrtc.org18530052012-07-03 10:41:54 +0000452 WebRtc_Word64 now = _clock.GetTimeInMS();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000453
454 CriticalSectionScoped lock(_criticalSectionRTCPSender);
455
niklase@google.com470e71d2011-07-07 08:21:25 +0000456 if(_method == kRtcpOff)
457 {
458 return false;
459 }
460
niklase@google.com470e71d2011-07-07 08:21:25 +0000461 if(!_audio && sendKeyframeBeforeRTP)
462 {
463 // for video key-frames we want to send the RTCP before the large key-frame
464 // if we have a 100 ms margin
465 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
466 }
467
468 if(now > _nextTimeToSendRTCP)
469 {
470 return true;
471
472 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
473 {
474 // wrap
475 return true;
476 }
477 return false;
478}
479
480WebRtc_UWord32
481RTCPSender::LastSendReport( WebRtc_UWord32& lastRTCPTime)
482{
483 CriticalSectionScoped lock(_criticalSectionRTCPSender);
484
485 lastRTCPTime = _lastRTCPTime[0];
486 return _lastSendReport[0];
487}
488
489WebRtc_UWord32
490RTCPSender::SendTimeOfSendReport(const WebRtc_UWord32 sendReport)
491{
492 CriticalSectionScoped lock(_criticalSectionRTCPSender);
493
494 // This is only saved when we are the sender
495 if((_lastSendReport[0] == 0) || (sendReport == 0))
496 {
497 return 0; // will be ignored
498 } else
499 {
500 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
501 {
502 if( _lastSendReport[i] == sendReport)
503 {
504 return _lastRTCPTime[i];
505 }
506 }
507 }
508 return 0;
509}
510
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000511WebRtc_Word32 RTCPSender::AddReportBlock(const WebRtc_UWord32 SSRC,
512 const RTCPReportBlock* reportBlock) {
513 if (reportBlock == NULL) {
514 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
515 "%s invalid argument", __FUNCTION__);
516 return -1;
517 }
518 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000519
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000520 if (_reportBlocks.size() >= RTCP_MAX_REPORT_BLOCKS) {
521 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
522 "%s invalid argument", __FUNCTION__);
523 return -1;
524 }
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000525 std::map<WebRtc_UWord32, RTCPReportBlock*>::iterator it =
526 _reportBlocks.find(SSRC);
527 if (it != _reportBlocks.end()) {
528 delete it->second;
529 _reportBlocks.erase(it);
530 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000531 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
532 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
533 _reportBlocks[SSRC] = copyReportBlock;
534 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000535}
536
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000537WebRtc_Word32 RTCPSender::RemoveReportBlock(const WebRtc_UWord32 SSRC) {
538 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000539
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000540 std::map<WebRtc_UWord32, RTCPReportBlock*>::iterator it =
541 _reportBlocks.find(SSRC);
542
543 if (it == _reportBlocks.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000544 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000545 }
546 delete it->second;
547 _reportBlocks.erase(it);
548 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000549}
550
551WebRtc_Word32
552RTCPSender::BuildSR(WebRtc_UWord8* rtcpbuffer,
553 WebRtc_UWord32& pos,
554 const WebRtc_UWord32 NTPsec,
555 const WebRtc_UWord32 NTPfrac,
556 const RTCPReportBlock* received)
557{
558 // sanity
559 if(pos + 52 >= IP_PACKET_SIZE)
560 {
561 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
562 return -2;
563 }
564 WebRtc_UWord32 RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000565
566 WebRtc_UWord32 posNumberOfReportBlocks = pos;
567 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
568
569 // Sender report
570 rtcpbuffer[pos++]=(WebRtc_UWord8)200;
571
572 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
573 {
574 // shift old
575 _lastSendReport[i+1] = _lastSendReport[i];
576 _lastRTCPTime[i+1] =_lastRTCPTime[i];
577 }
578
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000579 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac);
580 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000581
582 WebRtc_UWord32 freqHz = 90000; // For video
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000583 if(_audio) {
584 freqHz = _rtpRtcp.CurrentSendFrequencyHz();
niklase@google.com470e71d2011-07-07 08:21:25 +0000585 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000586 // The timestamp of this RTCP packet should be estimated as the timestamp of
587 // the frame being captured at this moment. We are calculating that
588 // timestamp as the last frame's timestamp + the time since the last frame
589 // was captured.
590 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (_clock.GetTimeInMS() -
591 last_frame_capture_time_ms_) * (freqHz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000592
593 // Add sender data
594 // Save for our length field
595 pos++;
596 pos++;
597
598 // Add our own SSRC
599 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
600 pos += 4;
601 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000602 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000603 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000604 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000605 pos += 4;
606 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
607 pos += 4;
608
609 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000610 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000611 pos += 4;
612
613 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000614 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000615 pos += 4;
616
617 WebRtc_UWord8 numberOfReportBlocks = 0;
618 WebRtc_Word32 retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
619 if(retVal < 0)
620 {
621 //
622 return retVal ;
623 }
624 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
625
626 WebRtc_UWord16 len = WebRtc_UWord16((pos/4) -1);
627 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
628 return 0;
629}
630
631
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000632WebRtc_Word32 RTCPSender::BuildSDEC(WebRtc_UWord8* rtcpbuffer,
633 WebRtc_UWord32& pos) {
634 size_t lengthCname = strlen(_CNAME);
635 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000636
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000637 // sanity
638 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
639 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
640 "%s invalid argument", __FUNCTION__);
641 return -2;
642 }
643 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000644
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000645 // We always need to add SDES CNAME
646 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(0x80 + 1 + _csrcCNAMEs.size());
647 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000648
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000649 // handle SDES length later on
650 WebRtc_UWord32 SDESLengthPos = pos;
651 pos++;
652 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000653
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000654 // Add our own SSRC
655 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
656 pos += 4;
657
658 // CNAME = 1
659 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(1);
660
661 //
662 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(lengthCname);
663
664 WebRtc_UWord16 SDESLength = 10;
665
666 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
667 pos += lengthCname;
668 SDESLength += (WebRtc_UWord16)lengthCname;
669
670 WebRtc_UWord16 padding = 0;
671 // We must have a zero field even if we have an even multiple of 4 bytes
672 if ((pos % 4) == 0) {
673 padding++;
674 rtcpbuffer[pos++]=0;
675 }
676 while ((pos % 4) != 0) {
677 padding++;
678 rtcpbuffer[pos++]=0;
679 }
680 SDESLength += padding;
681
682 std::map<WebRtc_UWord32, RTCPUtility::RTCPCnameInformation*>::iterator it =
683 _csrcCNAMEs.begin();
684
685 for(; it != _csrcCNAMEs.end(); it++) {
686 RTCPCnameInformation* cname = it->second;
687 WebRtc_UWord32 SSRC = it->first;
688
689 // Add SSRC
690 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000691 pos += 4;
692
693 // CNAME = 1
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000694 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000695
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000696 size_t length = strlen(cname->name);
697 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000698
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000699 rtcpbuffer[pos++]= static_cast<WebRtc_UWord8>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000700 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000701
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000702 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000703
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000704 pos += length;
705 SDESLength += length;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000706 WebRtc_UWord16 padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000707
708 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000709 if((pos % 4) == 0){
710 padding++;
711 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000712 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000713 while((pos % 4) != 0){
714 padding++;
715 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000716 }
717 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000718 }
719 // in 32-bit words minus one and we don't count the header
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000720 WebRtc_UWord16 buffer_length = (SDESLength / 4) - 1;
721 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
722 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000723 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000724}
725
726WebRtc_Word32
727RTCPSender::BuildRR(WebRtc_UWord8* rtcpbuffer,
728 WebRtc_UWord32& pos,
729 const WebRtc_UWord32 NTPsec,
730 const WebRtc_UWord32 NTPfrac,
731 const RTCPReportBlock* received)
732{
733 // sanity one block
734 if(pos + 32 >= IP_PACKET_SIZE)
735 {
736 return -2;
737 }
738 WebRtc_UWord32 posNumberOfReportBlocks = pos;
739
740 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
741 rtcpbuffer[pos++]=(WebRtc_UWord8)201;
742
743 // Save for our length field
744 pos++;
745 pos++;
746
747 // Add our own SSRC
748 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
749 pos += 4;
750
751 WebRtc_UWord8 numberOfReportBlocks = 0;
752 WebRtc_Word32 retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
753 if(retVal < 0)
754 {
755 return retVal;
756 }
757 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
758
759 WebRtc_UWord16 len = WebRtc_UWord16((pos)/4 -1);
760 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
761 return 0;
762}
763
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000764// From RFC 5450: Transmission Time Offsets in RTP Streams.
765// 0 1 2 3
766// 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
767// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
768// hdr |V=2|P| RC | PT=IJ=195 | length |
769// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
770// | inter-arrival jitter |
771// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
772// . .
773// . .
774// . .
775// | inter-arrival jitter |
776// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
777//
778// If present, this RTCP packet must be placed after a receiver report
779// (inside a compound RTCP packet), and MUST have the same value for RC
780// (reception report count) as the receiver report.
781
782WebRtc_Word32
783RTCPSender::BuildExtendedJitterReport(
784 WebRtc_UWord8* rtcpbuffer,
785 WebRtc_UWord32& pos,
786 const WebRtc_UWord32 jitterTransmissionTimeOffset)
787{
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000788 if (_reportBlocks.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000789 {
790 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
791 return 0;
792 }
793
794 // sanity
795 if(pos + 8 >= IP_PACKET_SIZE)
796 {
797 return -2;
798 }
799 // add picture loss indicator
800 WebRtc_UWord8 RC = 1;
801 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + RC;
802 rtcpbuffer[pos++]=(WebRtc_UWord8)195;
803
804 // Used fixed length of 2
805 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
806 rtcpbuffer[pos++]=(WebRtc_UWord8)(1);
807
808 // Add inter-arrival jitter
809 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
810 jitterTransmissionTimeOffset);
811 pos += 4;
812 return 0;
813}
814
niklase@google.com470e71d2011-07-07 08:21:25 +0000815WebRtc_Word32
816RTCPSender::BuildPLI(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
817{
818 // sanity
819 if(pos + 12 >= IP_PACKET_SIZE)
820 {
821 return -2;
822 }
823 // add picture loss indicator
824 WebRtc_UWord8 FMT = 1;
825 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
826 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
827
828 //Used fixed length of 2
829 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
830 rtcpbuffer[pos++]=(WebRtc_UWord8)(2);
831
832 // Add our own SSRC
833 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
834 pos += 4;
835
836 // Add the remote SSRC
837 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
838 pos += 4;
839 return 0;
840}
841
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000842WebRtc_Word32 RTCPSender::BuildFIR(WebRtc_UWord8* rtcpbuffer,
843 WebRtc_UWord32& pos,
844 bool repeat) {
845 // sanity
846 if(pos + 20 >= IP_PACKET_SIZE) {
847 return -2;
848 }
849 if (!repeat) {
850 _sequenceNumberFIR++; // do not increase if repetition
851 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000852
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000853 // add full intra request indicator
854 WebRtc_UWord8 FMT = 4;
855 rtcpbuffer[pos++] = (WebRtc_UWord8)0x80 + FMT;
856 rtcpbuffer[pos++] = (WebRtc_UWord8)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000857
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000858 //Length of 4
859 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
860 rtcpbuffer[pos++] = (WebRtc_UWord8)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000861
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000862 // Add our own SSRC
863 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
864 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000865
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000866 // RFC 5104 4.3.1.2. Semantics
867 // SSRC of media source
868 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
869 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
870 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
871 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000872
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000873 // Additional Feedback Control Information (FCI)
874 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
875 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000876
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000877 rtcpbuffer[pos++] = (WebRtc_UWord8)(_sequenceNumberFIR);
878 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
879 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
880 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
881 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000882}
883
884/*
885 0 1 2 3
886 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
887 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
888 | First | Number | PictureID |
889 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
890*/
891WebRtc_Word32
892RTCPSender::BuildSLI(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos, const WebRtc_UWord8 pictureID)
893{
894 // sanity
895 if(pos + 16 >= IP_PACKET_SIZE)
896 {
897 return -2;
898 }
899 // add slice loss indicator
900 WebRtc_UWord8 FMT = 2;
901 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
902 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
903
904 //Used fixed length of 3
905 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
906 rtcpbuffer[pos++]=(WebRtc_UWord8)(3);
907
908 // Add our own SSRC
909 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
910 pos += 4;
911
912 // Add the remote SSRC
913 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
914 pos += 4;
915
916 // Add first, number & picture ID 6 bits
917 // first = 0, 13 - bits
918 // number = 0x1fff, 13 - bits only ones for now
919 WebRtc_UWord32 sliField = (0x1fff << 6)+ (0x3f & pictureID);
920 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
921 pos += 4;
922 return 0;
923}
924
925/*
926 0 1 2 3
927 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
928 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
929 | PB |0| Payload Type| Native RPSI bit string |
930 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
931 | defined per codec ... | Padding (0) |
932 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
933*/
934/*
935* Note: not generic made for VP8
936*/
937WebRtc_Word32
938RTCPSender::BuildRPSI(WebRtc_UWord8* rtcpbuffer,
939 WebRtc_UWord32& pos,
940 const WebRtc_UWord64 pictureID,
941 const WebRtc_UWord8 payloadType)
942{
943 // sanity
944 if(pos + 24 >= IP_PACKET_SIZE)
945 {
946 return -2;
947 }
948 // add Reference Picture Selection Indication
949 WebRtc_UWord8 FMT = 3;
950 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
951 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
952
953 // calc length
954 WebRtc_UWord32 bitsRequired = 7;
955 WebRtc_UWord8 bytesRequired = 1;
956 while((pictureID>>bitsRequired) > 0)
957 {
958 bitsRequired += 7;
959 bytesRequired++;
960 }
961
962 WebRtc_UWord8 size = 3;
963 if(bytesRequired > 6)
964 {
965 size = 5;
966 } else if(bytesRequired > 2)
967 {
968 size = 4;
969 }
970 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
971 rtcpbuffer[pos++]=size;
972
973 // Add our own SSRC
974 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
975 pos += 4;
976
977 // Add the remote SSRC
978 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
979 pos += 4;
980
981 // calc padding length
982 WebRtc_UWord8 paddingBytes = 4-((2+bytesRequired)%4);
983 if(paddingBytes == 4)
984 {
985 paddingBytes = 0;
986 }
987 // add padding length in bits
988 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
989 pos++;
990
991 // add payload type
992 rtcpbuffer[pos] = payloadType;
993 pos++;
994
995 // add picture ID
996 for(int i = bytesRequired-1; i > 0; i--)
997 {
998 rtcpbuffer[pos] = 0x80 | WebRtc_UWord8(pictureID >> (i*7));
999 pos++;
1000 }
1001 // add last byte of picture ID
1002 rtcpbuffer[pos] = WebRtc_UWord8(pictureID & 0x7f);
1003 pos++;
1004
1005 // add padding
1006 for(int j = 0; j <paddingBytes; j++)
1007 {
1008 rtcpbuffer[pos] = 0;
1009 pos++;
1010 }
1011 return 0;
1012}
1013
1014WebRtc_Word32
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001015RTCPSender::BuildREMB(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1016{
1017 // sanity
1018 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1019 {
1020 return -2;
1021 }
1022 // add application layer feedback
1023 WebRtc_UWord8 FMT = 15;
1024 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1025 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
1026
1027 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1028 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1029
1030 // Add our own SSRC
1031 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1032 pos += 4;
1033
1034 // Remote SSRC must be 0
1035 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1036 pos += 4;
1037
1038 rtcpbuffer[pos++]='R';
1039 rtcpbuffer[pos++]='E';
1040 rtcpbuffer[pos++]='M';
1041 rtcpbuffer[pos++]='B';
1042
1043 rtcpbuffer[pos++] = _lengthRembSSRC;
1044 // 6 bit Exp
1045 // 18 bit mantissa
1046 WebRtc_UWord8 brExp = 0;
1047 for(WebRtc_UWord32 i=0; i<64; i++)
1048 {
1049 if(_rembBitrate <= ((WebRtc_UWord32)262143 << i))
1050 {
1051 brExp = i;
1052 break;
1053 }
1054 }
1055 const WebRtc_UWord32 brMantissa = (_rembBitrate >> brExp);
1056 rtcpbuffer[pos++]=(WebRtc_UWord8)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1057 rtcpbuffer[pos++]=(WebRtc_UWord8)(brMantissa >> 8);
1058 rtcpbuffer[pos++]=(WebRtc_UWord8)(brMantissa);
1059
1060 for (int i = 0; i < _lengthRembSSRC; i++)
1061 {
1062 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1063 pos += 4;
1064 }
1065 return 0;
1066}
1067
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001068void
1069RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001070{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001071 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001072 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001073}
1074
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001075WebRtc_Word32
1076RTCPSender::BuildTMMBR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001077{
1078 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1079 // If the sender is an owner of the TMMBN -> send TMMBR
1080 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1081
niklase@google.com470e71d2011-07-07 08:21:25 +00001082 // get current bounding set from RTCP receiver
1083 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001084 // store in candidateSet, allocates one extra slot
1085 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001086
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001087 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1088 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1089 // since RTCPreceiver is not doing the reverse we should be fine
1090 WebRtc_Word32 lengthOfBoundingSet
1091 = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001092
1093 if(lengthOfBoundingSet > 0)
1094 {
1095 for (WebRtc_Word32 i = 0; i < lengthOfBoundingSet; i++)
1096 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001097 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1098 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001099 {
1100 // do not send the same tuple
1101 return 0;
1102 }
1103 }
1104 if(!tmmbrOwner)
1105 {
1106 // use received bounding set as candidate set
1107 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001108 candidateSet->SetEntry(lengthOfBoundingSet,
1109 _tmmbr_Send,
1110 _packetOH_Send,
1111 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001112 int numCandidates = lengthOfBoundingSet+ 1;
1113
1114 // find bounding set
1115 TMMBRSet* boundingSet = NULL;
1116 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1117 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1118 {
1119 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1120 }
1121 if(!tmmbrOwner)
1122 {
1123 // did not enter bounding set, no meaning to send this request
1124 return 0;
1125 }
1126 }
1127 }
1128
1129 if(_tmmbr_Send)
1130 {
1131 // sanity
1132 if(pos + 20 >= IP_PACKET_SIZE)
1133 {
1134 return -2;
1135 }
1136 // add TMMBR indicator
1137 WebRtc_UWord8 FMT = 3;
1138 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1139 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1140
1141 //Length of 4
1142 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1143 rtcpbuffer[pos++]=(WebRtc_UWord8)(4);
1144
1145 // Add our own SSRC
1146 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1147 pos += 4;
1148
1149 // RFC 5104 4.2.1.2. Semantics
1150
1151 // SSRC of media source
1152 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1153 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1154 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1155 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1156
1157 // Additional Feedback Control Information (FCI)
1158 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1159 pos += 4;
1160
1161 WebRtc_UWord32 bitRate = _tmmbr_Send*1000;
1162 WebRtc_UWord32 mmbrExp = 0;
1163 for(WebRtc_UWord32 i=0;i<64;i++)
1164 {
1165 if(bitRate <= ((WebRtc_UWord32)131071 << i))
1166 {
1167 mmbrExp = i;
1168 break;
1169 }
1170 }
1171 WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp);
1172
1173 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1174 rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);
1175 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1176 rtcpbuffer[pos++]=(WebRtc_UWord8)(_packetOH_Send);
1177 }
1178 return 0;
1179}
1180
1181WebRtc_Word32
1182RTCPSender::BuildTMMBN(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1183{
1184 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1185 if(boundingSet == NULL)
1186 {
1187 return -1;
1188 }
1189 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001190 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001191 {
1192 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1193 return -2;
1194 }
1195 WebRtc_UWord8 FMT = 4;
1196 // add TMMBN indicator
1197 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1198 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1199
1200 //Add length later
1201 int posLength = pos;
1202 pos++;
1203 pos++;
1204
1205 // Add our own SSRC
1206 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1207 pos += 4;
1208
1209 // RFC 5104 4.2.2.2. Semantics
1210
1211 // SSRC of media source
1212 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1213 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1214 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1215 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1216
1217 // Additional Feedback Control Information (FCI)
1218 int numBoundingSet = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001219 for(WebRtc_UWord32 n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001220 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001221 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001222 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001223 WebRtc_UWord32 tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001224 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1225 pos += 4;
1226
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001227 WebRtc_UWord32 bitRate = boundingSet->Tmmbr(n) * 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001228 WebRtc_UWord32 mmbrExp = 0;
1229 for(int i=0; i<64; i++)
1230 {
1231 if(bitRate <= ((WebRtc_UWord32)131071 << i))
1232 {
1233 mmbrExp = i;
1234 break;
1235 }
1236 }
1237 WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp);
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001238 WebRtc_UWord32 measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001239
1240 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1241 rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);
1242 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1243 rtcpbuffer[pos++]=(WebRtc_UWord8)(measuredOH);
1244 numBoundingSet++;
1245 }
1246 }
1247 WebRtc_UWord16 length= (WebRtc_UWord16)(2+2*numBoundingSet);
1248 rtcpbuffer[posLength++]=(WebRtc_UWord8)(length>>8);
1249 rtcpbuffer[posLength]=(WebRtc_UWord8)(length);
1250 return 0;
1251}
1252
1253WebRtc_Word32
1254RTCPSender::BuildAPP(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1255{
1256 // sanity
1257 if(_appData == NULL)
1258 {
1259 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1260 return -1;
1261 }
1262 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1263 {
1264 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1265 return -2;
1266 }
1267 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + _appSubType;
1268
1269 // Add APP ID
1270 rtcpbuffer[pos++]=(WebRtc_UWord8)204;
1271
1272 WebRtc_UWord16 length = (_appLength>>2) + 2; // include SSRC and name
1273 rtcpbuffer[pos++]=(WebRtc_UWord8)(length>>8);
1274 rtcpbuffer[pos++]=(WebRtc_UWord8)(length);
1275
1276 // Add our own SSRC
1277 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1278 pos += 4;
1279
1280 // Add our application name
1281 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1282 pos += 4;
1283
1284 // Add the data
1285 memcpy(rtcpbuffer +pos, _appData,_appLength);
1286 pos += _appLength;
1287 return 0;
1288}
1289
1290WebRtc_Word32
1291RTCPSender::BuildNACK(WebRtc_UWord8* rtcpbuffer,
1292 WebRtc_UWord32& pos,
1293 const WebRtc_Word32 nackSize,
1294 const WebRtc_UWord16* nackList)
1295{
1296 // sanity
1297 if(pos + 16 >= IP_PACKET_SIZE)
1298 {
1299 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1300 return -2;
1301 }
1302
1303 // int size, WebRtc_UWord16* nackList
1304 // add nack list
1305 WebRtc_UWord8 FMT = 1;
1306 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1307 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1308
1309 rtcpbuffer[pos++]=(WebRtc_UWord8) 0;
1310 int nackSizePos = pos;
1311 rtcpbuffer[pos++]=(WebRtc_UWord8)(3); //setting it to one kNACK signal as default
1312
1313 // Add our own SSRC
1314 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1315 pos += 4;
1316
1317 // Add the remote SSRC
1318 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1319 pos += 4;
1320
1321 // add the list
1322 int i = 0;
1323 int numOfNackFields = 0;
1324 while(nackSize > i && numOfNackFields < 253)
1325 {
1326 WebRtc_UWord16 nack = nackList[i];
1327 // put dow our sequence number
1328 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, nack);
1329 pos += 2;
1330
1331 i++;
1332 numOfNackFields++;
1333 if(nackSize > i)
1334 {
1335 bool moreThan16Away = (WebRtc_UWord16(nack+16) < nackList[i])?true: false;
1336 if(!moreThan16Away)
1337 {
1338 // check for a wrap
1339 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1340 {
1341 // wrap
1342 moreThan16Away = true;
1343 }
1344 }
1345 if(moreThan16Away)
1346 {
1347 // next is more than 16 away
1348 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1349 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1350 } else
1351 {
1352 // build our bitmask
1353 WebRtc_UWord16 bitmask = 0;
1354
1355 bool within16Away = (WebRtc_UWord16(nack+16) > nackList[i])?true: false;
1356 if(within16Away)
1357 {
1358 // check for a wrap
1359 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1360 {
1361 // wrap
1362 within16Away = false;
1363 }
1364 }
1365
1366 while( nackSize > i && within16Away)
1367 {
1368 WebRtc_Word16 shift = (nackList[i]-nack)-1;
1369 assert(!(shift > 15) && !(shift < 0));
1370
1371 bitmask += (1<< shift);
1372 i++;
1373 if(nackSize > i)
1374 {
1375 within16Away = (WebRtc_UWord16(nack+16) > nackList[i])?true: false;
1376 if(within16Away)
1377 {
1378 // check for a wrap
1379 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1380 {
1381 // wrap
1382 within16Away = false;
1383 }
1384 }
1385 }
1386 }
1387 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, bitmask);
1388 pos += 2;
1389 }
1390 // sanity do we have room from one more 4 byte block?
1391 if(pos + 4 >= IP_PACKET_SIZE)
1392 {
1393 return -2;
1394 }
1395 } else
1396 {
1397 // no more in the list
1398 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1399 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1400 }
1401 }
1402 rtcpbuffer[nackSizePos]=(WebRtc_UWord8)(2+numOfNackFields);
1403 return 0;
1404}
1405
1406WebRtc_Word32
1407RTCPSender::BuildBYE(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1408{
1409 // sanity
1410 if(pos + 8 >= IP_PACKET_SIZE)
1411 {
1412 return -2;
1413 }
1414 if(_includeCSRCs)
1415 {
1416 // Add a bye packet
1417 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1418 rtcpbuffer[pos++]=(WebRtc_UWord8)203;
1419
1420 // length
1421 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1422 rtcpbuffer[pos++]=(WebRtc_UWord8)(1 + _CSRCs);
1423
1424 // Add our own SSRC
1425 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1426 pos += 4;
1427
1428 // add CSRCs
1429 for(int i = 0; i < _CSRCs; i++)
1430 {
1431 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1432 pos += 4;
1433 }
1434 } else
1435 {
1436 // Add a bye packet
1437 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1; // number of SSRC+CSRCs
1438 rtcpbuffer[pos++]=(WebRtc_UWord8)203;
1439
1440 // length
1441 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1442 rtcpbuffer[pos++]=(WebRtc_UWord8)1;
1443
1444 // Add our own SSRC
1445 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1446 pos += 4;
1447 }
1448 return 0;
1449}
1450
1451WebRtc_Word32
1452RTCPSender::BuildVoIPMetric(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1453{
1454 // sanity
1455 if(pos + 44 >= IP_PACKET_SIZE)
1456 {
1457 return -2;
1458 }
1459
1460 // Add XR header
1461 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
1462 rtcpbuffer[pos++]=(WebRtc_UWord8)207;
1463
1464 WebRtc_UWord32 XRLengthPos = pos;
1465
1466 // handle length later on
1467 pos++;
1468 pos++;
1469
1470 // Add our own SSRC
1471 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1472 pos += 4;
1473
1474 // Add a VoIP metrics block
1475 rtcpbuffer[pos++]=7;
1476 rtcpbuffer[pos++]=0;
1477 rtcpbuffer[pos++]=0;
1478 rtcpbuffer[pos++]=8;
1479
1480 // Add the remote SSRC
1481 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1482 pos += 4;
1483
1484 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1485 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1486 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1487 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1488
1489 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.burstDuration >> 8);
1490 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.burstDuration);
1491 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.gapDuration >> 8);
1492 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.gapDuration);
1493
1494 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.roundTripDelay >> 8);
1495 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.roundTripDelay);
1496 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.endSystemDelay >> 8);
1497 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.endSystemDelay);
1498
1499 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1500 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1501 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1502 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1503
1504 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1505 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1506 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1507 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1508
1509 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1510 rtcpbuffer[pos++] = 0; // reserved
1511 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBnominal >> 8);
1512 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBnominal);
1513
1514 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBmax >> 8);
1515 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBmax);
1516 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBabsMax >> 8);
1517 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBabsMax);
1518
1519 rtcpbuffer[XRLengthPos]=(WebRtc_UWord8)(0);
1520 rtcpbuffer[XRLengthPos+1]=(WebRtc_UWord8)(10);
1521 return 0;
1522}
1523
1524WebRtc_Word32
1525RTCPSender::SendRTCP(const WebRtc_UWord32 packetTypeFlags,
1526 const WebRtc_Word32 nackSize, // NACK
1527 const WebRtc_UWord16* nackList, // NACK
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001528 const bool repeat, // FIR
niklase@google.com470e71d2011-07-07 08:21:25 +00001529 const WebRtc_UWord64 pictureID) // SLI & RPSI
1530{
1531 WebRtc_UWord32 rtcpPacketTypeFlags = packetTypeFlags;
1532 WebRtc_UWord32 pos = 0;
1533 WebRtc_UWord8 rtcpbuffer[IP_PACKET_SIZE];
1534
niklase@google.com470e71d2011-07-07 08:21:25 +00001535 do // only to be able to use break :) (and the critsect must be inside its own scope)
1536 {
1537 // collect the received information
1538 RTCPReportBlock received;
1539 bool hasReceived = false;
1540 WebRtc_UWord32 NTPsec = 0;
1541 WebRtc_UWord32 NTPfrac = 0;
xians@webrtc.org8738d272011-11-25 13:43:53 +00001542 bool rtcpCompound = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001543 WebRtc_UWord32 jitterTransmissionOffset = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001544
xians@webrtc.org8738d272011-11-25 13:43:53 +00001545 {
1546 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1547 if(_method == kRtcpOff)
1548 {
1549 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1550 "%s invalid state", __FUNCTION__);
1551 return -1;
1552 }
1553 rtcpCompound = (_method == kRtcpCompound) ? true : false;
1554 }
1555
1556 if (rtcpCompound ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001557 rtcpPacketTypeFlags & kRtcpReport ||
1558 rtcpPacketTypeFlags & kRtcpSr ||
1559 rtcpPacketTypeFlags & kRtcpRr)
1560 {
1561 // get statistics from our RTPreceiver outside critsect
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001562 if(_rtpRtcp.ReportBlockStatistics(&received.fractionLost,
1563 &received.cumulativeLost,
1564 &received.extendedHighSeqNum,
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001565 &received.jitter,
1566 &jitterTransmissionOffset) == 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001567 {
1568 hasReceived = true;
1569
1570 WebRtc_UWord32 lastReceivedRRNTPsecs = 0;
1571 WebRtc_UWord32 lastReceivedRRNTPfrac = 0;
1572 WebRtc_UWord32 remoteSR = 0;
1573
1574 // ok even if we have not received a SR, we will send 0 in that case
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001575 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1576 lastReceivedRRNTPfrac,
1577 remoteSR);
niklase@google.com470e71d2011-07-07 08:21:25 +00001578
1579 // get our NTP as late as possible to avoid a race
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001580 _clock.CurrentNTP(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001581
1582 // Delay since last received report
1583 WebRtc_UWord32 delaySinceLastReceivedSR = 0;
1584 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
1585 {
1586 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1587 WebRtc_UWord32 now=NTPsec&0x0000FFFF;
1588 now <<=16;
1589 now += (NTPfrac&0xffff0000)>>16;
1590
1591 WebRtc_UWord32 receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
1592 receiveTime <<=16;
1593 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1594
1595 delaySinceLastReceivedSR = now-receiveTime;
1596 }
1597 received.delaySinceLastSR = delaySinceLastReceivedSR;
1598 received.lastSR = remoteSR;
1599 } else
1600 {
1601 // we need to send our NTP even if we dont have received any reports
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001602 _clock.CurrentNTP(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001603 }
1604 }
1605
1606 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1607
1608 if(_TMMBR ) // attach TMMBR to send and receive reports
1609 {
1610 rtcpPacketTypeFlags |= kRtcpTmmbr;
1611 }
1612 if(_appSend)
1613 {
1614 rtcpPacketTypeFlags |= kRtcpApp;
1615 _appSend = false;
1616 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001617 if(_REMB && _sendREMB)
1618 {
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +00001619 // Always attach REMB to SR if that is configured. Note that REMB is
1620 // only sent on one of the RTP modules in the REMB group.
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001621 rtcpPacketTypeFlags |= kRtcpRemb;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001622 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001623 if(_xrSendVoIPMetric)
1624 {
1625 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1626 _xrSendVoIPMetric = false;
1627 }
1628 if(_sendTMMBN) // set when having received a TMMBR
1629 {
1630 rtcpPacketTypeFlags |= kRtcpTmmbn;
1631 _sendTMMBN = false;
1632 }
1633
1634 if(_method == kRtcpCompound)
1635 {
1636 if(_sending)
1637 {
1638 rtcpPacketTypeFlags |= kRtcpSr;
1639 } else
1640 {
1641 rtcpPacketTypeFlags |= kRtcpRr;
1642 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001643 if (_IJ && hasReceived)
1644 {
1645 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1646 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001647 } else if(_method == kRtcpNonCompound)
1648 {
1649 if(rtcpPacketTypeFlags & kRtcpReport)
1650 {
1651 if(_sending)
1652 {
1653 rtcpPacketTypeFlags |= kRtcpSr;
1654 } else
1655 {
1656 rtcpPacketTypeFlags |= kRtcpRr;
1657 }
1658 }
1659 }
1660 if( rtcpPacketTypeFlags & kRtcpRr ||
1661 rtcpPacketTypeFlags & kRtcpSr)
1662 {
1663 // generate next time to send a RTCP report
1664 // seeded from RTP constructor
1665 WebRtc_Word32 random = rand() % 1000;
1666 WebRtc_Word32 timeToNext = RTCP_INTERVAL_AUDIO_MS;
1667
1668 if(_audio)
1669 {
1670 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
1671 }else
1672 {
1673 WebRtc_UWord32 minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1674 if(_sending)
1675 {
1676 // calc bw for video 360/sendBW in kbit/s
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001677 WebRtc_UWord32 sendBitrateKbit = 0;
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001678 WebRtc_UWord32 videoRate = 0;
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001679 WebRtc_UWord32 fecRate = 0;
1680 WebRtc_UWord32 nackRate = 0;
1681 _rtpRtcp.BitrateSent(&sendBitrateKbit,
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001682 &videoRate,
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001683 &fecRate,
1684 &nackRate);
1685 sendBitrateKbit /= 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001686 if(sendBitrateKbit != 0)
1687 {
1688 minIntervalMs = 360000/sendBitrateKbit;
1689 }
1690 }
1691 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1692 {
1693 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1694 }
1695 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1696 }
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001697 _nextTimeToSendRTCP = _clock.GetTimeInMS() + timeToNext;
niklase@google.com470e71d2011-07-07 08:21:25 +00001698 }
1699
1700 // if the data does not fitt in the packet we fill it as much as possible
1701 WebRtc_Word32 buildVal = 0;
1702
1703 if(rtcpPacketTypeFlags & kRtcpSr)
1704 {
1705 if(hasReceived)
1706 {
1707 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
1708 } else
1709 {
1710 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac);
1711 }
1712 if(buildVal == -1)
1713 {
1714 return -1; // error
1715
1716 }else if(buildVal == -2)
1717 {
1718 break; // out of buffer
1719 }
1720 buildVal = BuildSDEC(rtcpbuffer, pos);
1721 if(buildVal == -1)
1722 {
1723 return -1; // error
1724
1725 }else if(buildVal == -2)
1726 {
1727 break; // out of buffer
1728 }
1729
1730 }else if(rtcpPacketTypeFlags & kRtcpRr)
1731 {
1732 if(hasReceived)
1733 {
1734 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
1735 }else
1736 {
1737 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
1738 }
1739 if(buildVal == -1)
1740 {
1741 return -1; // error
1742
1743 }else if(buildVal == -2)
1744 {
1745 break; // out of buffer
1746 }
1747 // only of set
1748 if(_CNAME[0] != 0)
1749 {
1750 buildVal = BuildSDEC(rtcpbuffer, pos);
1751 if(buildVal == -1)
1752 {
1753 return -1; // error
1754 }
1755 }
1756 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001757 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1758 {
1759 // If present, this RTCP packet must be placed after a
1760 // receiver report.
1761 buildVal = BuildExtendedJitterReport(rtcpbuffer,
1762 pos,
1763 jitterTransmissionOffset);
1764 if(buildVal == -1)
1765 {
1766 return -1; // error
1767 }
1768 else if(buildVal == -2)
1769 {
1770 break; // out of buffer
1771 }
1772 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001773 if(rtcpPacketTypeFlags & kRtcpPli)
1774 {
1775 buildVal = BuildPLI(rtcpbuffer, pos);
1776 if(buildVal == -1)
1777 {
1778 return -1; // error
1779
1780 }else if(buildVal == -2)
1781 {
1782 break; // out of buffer
1783 }
1784 }
1785 if(rtcpPacketTypeFlags & kRtcpFir)
1786 {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001787 buildVal = BuildFIR(rtcpbuffer, pos, repeat);
niklase@google.com470e71d2011-07-07 08:21:25 +00001788 if(buildVal == -1)
1789 {
1790 return -1; // error
1791
1792 }else if(buildVal == -2)
1793 {
1794 break; // out of buffer
1795 }
1796 }
1797 if(rtcpPacketTypeFlags & kRtcpSli)
1798 {
1799 buildVal = BuildSLI(rtcpbuffer, pos, (WebRtc_UWord8)pictureID);
1800 if(buildVal == -1)
1801 {
1802 return -1; // error
1803
1804 }else if(buildVal == -2)
1805 {
1806 break; // out of buffer
1807 }
1808 }
1809 if(rtcpPacketTypeFlags & kRtcpRpsi)
1810 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001811 const WebRtc_Word8 payloadType = _rtpRtcp.SendPayloadType();
niklase@google.com470e71d2011-07-07 08:21:25 +00001812 if(payloadType == -1)
1813 {
1814 return -1;
1815 }
1816 buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (WebRtc_UWord8)payloadType);
1817 if(buildVal == -1)
1818 {
1819 return -1; // error
1820
1821 }else if(buildVal == -2)
1822 {
1823 break; // out of buffer
1824 }
1825 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001826 if(rtcpPacketTypeFlags & kRtcpRemb)
1827 {
1828 buildVal = BuildREMB(rtcpbuffer, pos);
1829 if(buildVal == -1)
1830 {
1831 return -1; // error
1832
1833 }else if(buildVal == -2)
1834 {
1835 break; // out of buffer
1836 }
1837 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001838 if(rtcpPacketTypeFlags & kRtcpBye)
1839 {
1840 buildVal = BuildBYE(rtcpbuffer, pos);
1841 if(buildVal == -1)
1842 {
1843 return -1; // error
1844
1845 }else if(buildVal == -2)
1846 {
1847 break; // out of buffer
1848 }
1849 }
1850 if(rtcpPacketTypeFlags & kRtcpApp)
1851 {
1852 buildVal = BuildAPP(rtcpbuffer, pos);
1853 if(buildVal == -1)
1854 {
1855 return -1; // error
1856
1857 }else if(buildVal == -2)
1858 {
1859 break; // out of buffer
1860 }
1861 }
1862 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1863 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001864 buildVal = BuildTMMBR(rtcpbuffer, pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001865 if(buildVal == -1)
1866 {
1867 return -1; // error
1868
1869 }else if(buildVal == -2)
1870 {
1871 break; // out of buffer
1872 }
1873 }
1874 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1875 {
1876 buildVal = BuildTMMBN(rtcpbuffer, pos);
1877 if(buildVal == -1)
1878 {
1879 return -1; // error
1880
1881 }else if(buildVal == -2)
1882 {
1883 break; // out of buffer
1884 }
1885 }
1886 if(rtcpPacketTypeFlags & kRtcpNack)
1887 {
1888 buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList);
1889 if(buildVal == -1)
1890 {
1891 return -1; // error
1892
1893 }else if(buildVal == -2)
1894 {
1895 break; // out of buffer
1896 }
1897 }
1898 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1899 {
1900 buildVal = BuildVoIPMetric(rtcpbuffer, pos);
1901 if(buildVal == -1)
1902 {
1903 return -1; // error
1904
1905 }else if(buildVal == -2)
1906 {
1907 break; // out of buffer
1908 }
1909 }
1910 }while (false);
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001911 // Sanity don't send empty packets.
1912 if (pos == 0)
1913 {
1914 return -1;
1915 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001916 return SendToNetwork(rtcpbuffer, (WebRtc_UWord16)pos);
1917}
1918
1919WebRtc_Word32
1920RTCPSender::SendToNetwork(const WebRtc_UWord8* dataBuffer,
1921 const WebRtc_UWord16 length)
1922{
1923 CriticalSectionScoped lock(_criticalSectionTransport);
1924 if(_cbTransport)
1925 {
1926 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1927 {
1928 return 0;
1929 }
1930 }
1931 return -1;
1932}
1933
1934WebRtc_Word32
1935RTCPSender::SetCSRCStatus(const bool include)
1936{
1937 _includeCSRCs = include;
1938 return 0;
1939}
1940
1941WebRtc_Word32
1942RTCPSender::SetCSRCs(const WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize],
1943 const WebRtc_UWord8 arrLength)
1944{
1945 if(arrLength > kRtpCsrcSize)
1946 {
1947 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1948 assert(false);
1949 return -1;
1950 }
1951
1952 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1953
1954 for(int i = 0; i < arrLength;i++)
1955 {
1956 _CSRC[i] = arrOfCSRC[i];
1957 }
1958 _CSRCs = arrLength;
1959 return 0;
1960}
1961
1962WebRtc_Word32
1963RTCPSender::SetApplicationSpecificData(const WebRtc_UWord8 subType,
1964 const WebRtc_UWord32 name,
1965 const WebRtc_UWord8* data,
1966 const WebRtc_UWord16 length)
1967{
1968 if(length %4 != 0)
1969 {
1970 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1971 return -1;
1972 }
1973 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1974
1975 if(_appData)
1976 {
1977 delete [] _appData;
1978 }
1979
1980 _appSend = true;
1981 _appSubType = subType;
1982 _appName = name;
1983 _appData = new WebRtc_UWord8[length];
1984 _appLength = length;
1985 memcpy(_appData, data, length);
1986 return 0;
1987}
1988
1989WebRtc_Word32
1990RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
1991{
1992 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1993 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
1994
1995 _xrSendVoIPMetric = true;
1996 return 0;
1997}
1998
1999// called under critsect _criticalSectionRTCPSender
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002000WebRtc_Word32 RTCPSender::AddReportBlocks(WebRtc_UWord8* rtcpbuffer,
2001 WebRtc_UWord32& pos,
2002 WebRtc_UWord8& numberOfReportBlocks,
2003 const RTCPReportBlock* received,
2004 const WebRtc_UWord32 NTPsec,
2005 const WebRtc_UWord32 NTPfrac) {
2006 // sanity one block
2007 if(pos + 24 >= IP_PACKET_SIZE) {
2008 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2009 "%s invalid argument", __FUNCTION__);
2010 return -1;
2011 }
2012 numberOfReportBlocks = _reportBlocks.size();
2013 if (received) {
2014 // add our multiple RR to numberOfReportBlocks
2015 numberOfReportBlocks++;
2016 }
2017 if (received) {
2018 // answer to the one that sends to me
2019 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac);
2020
2021 // Remote SSRC
2022 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
2023 pos += 4;
2024
2025 // fraction lost
2026 rtcpbuffer[pos++]=received->fractionLost;
2027
2028 // cumulative loss
2029 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2030 received->cumulativeLost);
2031 pos += 3;
2032 // extended highest seq_no, contain the highest sequence number received
2033 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2034 received->extendedHighSeqNum);
2035 pos += 4;
2036
2037 //Jitter
2038 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
2039 pos += 4;
2040
2041 // Last SR timestamp, our NTP time when we received the last report
2042 // This is the value that we read from the send report packet not when we
2043 // received it...
2044 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
2045 pos += 4;
2046
2047 // Delay since last received report,time since we received the report
2048 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2049 received->delaySinceLastSR);
2050 pos += 4;
2051 }
2052 if ((pos + _reportBlocks.size() * 24) >= IP_PACKET_SIZE) {
2053 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2054 "%s invalid argument", __FUNCTION__);
2055 return -1;
2056 }
2057 std::map<WebRtc_UWord32, RTCPReportBlock*>::iterator it =
2058 _reportBlocks.begin();
2059
2060 for (; it != _reportBlocks.end(); it++) {
2061 // we can have multiple report block in a conference
2062 WebRtc_UWord32 remoteSSRC = it->first;
2063 RTCPReportBlock* reportBlock = it->second;
2064 if (reportBlock) {
2065 // Remote SSRC
2066 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
2067 pos += 4;
2068
2069 // fraction lost
2070 rtcpbuffer[pos++] = reportBlock->fractionLost;
2071
2072 // cumulative loss
2073 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2074 reportBlock->cumulativeLost);
2075 pos += 3;
2076
2077 // extended highest seq_no, contain the highest sequence number received
2078 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2079 reportBlock->extendedHighSeqNum);
2080 pos += 4;
2081
2082 //Jitter
2083 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2084 reportBlock->jitter);
2085 pos += 4;
2086
2087 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2088 reportBlock->lastSR);
2089 pos += 4;
2090
2091 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2092 reportBlock->delaySinceLastSR);
2093 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002094 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002095 }
2096 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00002097}
2098
2099// no callbacks allowed inside this function
2100WebRtc_Word32
2101RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
2102 const WebRtc_UWord32 maxBitrateKbit)
2103{
2104 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2105
2106 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2107 {
2108 _sendTMMBN = true;
2109 return 0;
2110 }
2111 return -1;
2112}
niklase@google.com470e71d2011-07-07 08:21:25 +00002113} // namespace webrtc