blob: 789eaf1b5628981ed02d41a7fde8da0191723feb [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 }
525 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
526 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
527 _reportBlocks[SSRC] = copyReportBlock;
528 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000529}
530
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000531WebRtc_Word32 RTCPSender::RemoveReportBlock(const WebRtc_UWord32 SSRC) {
532 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000533
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000534 std::map<WebRtc_UWord32, RTCPReportBlock*>::iterator it =
535 _reportBlocks.find(SSRC);
536
537 if (it == _reportBlocks.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000538 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000539 }
540 delete it->second;
541 _reportBlocks.erase(it);
542 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000543}
544
545WebRtc_Word32
546RTCPSender::BuildSR(WebRtc_UWord8* rtcpbuffer,
547 WebRtc_UWord32& pos,
548 const WebRtc_UWord32 NTPsec,
549 const WebRtc_UWord32 NTPfrac,
550 const RTCPReportBlock* received)
551{
552 // sanity
553 if(pos + 52 >= IP_PACKET_SIZE)
554 {
555 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
556 return -2;
557 }
558 WebRtc_UWord32 RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000559
560 WebRtc_UWord32 posNumberOfReportBlocks = pos;
561 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
562
563 // Sender report
564 rtcpbuffer[pos++]=(WebRtc_UWord8)200;
565
566 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
567 {
568 // shift old
569 _lastSendReport[i+1] = _lastSendReport[i];
570 _lastRTCPTime[i+1] =_lastRTCPTime[i];
571 }
572
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000573 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac);
574 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000575
576 WebRtc_UWord32 freqHz = 90000; // For video
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000577 if(_audio) {
578 freqHz = _rtpRtcp.CurrentSendFrequencyHz();
niklase@google.com470e71d2011-07-07 08:21:25 +0000579 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000580 // The timestamp of this RTCP packet should be estimated as the timestamp of
581 // the frame being captured at this moment. We are calculating that
582 // timestamp as the last frame's timestamp + the time since the last frame
583 // was captured.
584 RTPtime = start_timestamp_ + last_rtp_timestamp_ + (_clock.GetTimeInMS() -
585 last_frame_capture_time_ms_) * (freqHz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000586
587 // Add sender data
588 // Save for our length field
589 pos++;
590 pos++;
591
592 // Add our own SSRC
593 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
594 pos += 4;
595 // NTP
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000596 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000597 pos += 4;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000598 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000599 pos += 4;
600 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
601 pos += 4;
602
603 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000604 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000605 pos += 4;
606
607 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000608 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000609 pos += 4;
610
611 WebRtc_UWord8 numberOfReportBlocks = 0;
612 WebRtc_Word32 retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
613 if(retVal < 0)
614 {
615 //
616 return retVal ;
617 }
618 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
619
620 WebRtc_UWord16 len = WebRtc_UWord16((pos/4) -1);
621 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
622 return 0;
623}
624
625
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000626WebRtc_Word32 RTCPSender::BuildSDEC(WebRtc_UWord8* rtcpbuffer,
627 WebRtc_UWord32& pos) {
628 size_t lengthCname = strlen(_CNAME);
629 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000630
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000631 // sanity
632 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
633 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
634 "%s invalid argument", __FUNCTION__);
635 return -2;
636 }
637 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000638
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000639 // We always need to add SDES CNAME
640 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(0x80 + 1 + _csrcCNAMEs.size());
641 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000642
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000643 // handle SDES length later on
644 WebRtc_UWord32 SDESLengthPos = pos;
645 pos++;
646 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000647
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000648 // Add our own SSRC
649 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
650 pos += 4;
651
652 // CNAME = 1
653 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(1);
654
655 //
656 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(lengthCname);
657
658 WebRtc_UWord16 SDESLength = 10;
659
660 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
661 pos += lengthCname;
662 SDESLength += (WebRtc_UWord16)lengthCname;
663
664 WebRtc_UWord16 padding = 0;
665 // We must have a zero field even if we have an even multiple of 4 bytes
666 if ((pos % 4) == 0) {
667 padding++;
668 rtcpbuffer[pos++]=0;
669 }
670 while ((pos % 4) != 0) {
671 padding++;
672 rtcpbuffer[pos++]=0;
673 }
674 SDESLength += padding;
675
676 std::map<WebRtc_UWord32, RTCPUtility::RTCPCnameInformation*>::iterator it =
677 _csrcCNAMEs.begin();
678
679 for(; it != _csrcCNAMEs.end(); it++) {
680 RTCPCnameInformation* cname = it->second;
681 WebRtc_UWord32 SSRC = it->first;
682
683 // Add SSRC
684 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000685 pos += 4;
686
687 // CNAME = 1
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000688 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000689
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000690 size_t length = strlen(cname->name);
691 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000692
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000693 rtcpbuffer[pos++]= static_cast<WebRtc_UWord8>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000694 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000695
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000696 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000697
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000698 pos += length;
699 SDESLength += length;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000700 WebRtc_UWord16 padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000701
702 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000703 if((pos % 4) == 0){
704 padding++;
705 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000706 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000707 while((pos % 4) != 0){
708 padding++;
709 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000710 }
711 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000712 }
713 // in 32-bit words minus one and we don't count the header
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000714 WebRtc_UWord16 buffer_length = (SDESLength / 4) - 1;
715 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
716 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000717 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000718}
719
720WebRtc_Word32
721RTCPSender::BuildRR(WebRtc_UWord8* rtcpbuffer,
722 WebRtc_UWord32& pos,
723 const WebRtc_UWord32 NTPsec,
724 const WebRtc_UWord32 NTPfrac,
725 const RTCPReportBlock* received)
726{
727 // sanity one block
728 if(pos + 32 >= IP_PACKET_SIZE)
729 {
730 return -2;
731 }
732 WebRtc_UWord32 posNumberOfReportBlocks = pos;
733
734 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
735 rtcpbuffer[pos++]=(WebRtc_UWord8)201;
736
737 // Save for our length field
738 pos++;
739 pos++;
740
741 // Add our own SSRC
742 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
743 pos += 4;
744
745 WebRtc_UWord8 numberOfReportBlocks = 0;
746 WebRtc_Word32 retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
747 if(retVal < 0)
748 {
749 return retVal;
750 }
751 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
752
753 WebRtc_UWord16 len = WebRtc_UWord16((pos)/4 -1);
754 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
755 return 0;
756}
757
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000758// From RFC 5450: Transmission Time Offsets in RTP Streams.
759// 0 1 2 3
760// 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
761// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
762// hdr |V=2|P| RC | PT=IJ=195 | length |
763// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
764// | inter-arrival jitter |
765// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
766// . .
767// . .
768// . .
769// | inter-arrival jitter |
770// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
771//
772// If present, this RTCP packet must be placed after a receiver report
773// (inside a compound RTCP packet), and MUST have the same value for RC
774// (reception report count) as the receiver report.
775
776WebRtc_Word32
777RTCPSender::BuildExtendedJitterReport(
778 WebRtc_UWord8* rtcpbuffer,
779 WebRtc_UWord32& pos,
780 const WebRtc_UWord32 jitterTransmissionTimeOffset)
781{
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000782 if (_reportBlocks.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000783 {
784 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
785 return 0;
786 }
787
788 // sanity
789 if(pos + 8 >= IP_PACKET_SIZE)
790 {
791 return -2;
792 }
793 // add picture loss indicator
794 WebRtc_UWord8 RC = 1;
795 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + RC;
796 rtcpbuffer[pos++]=(WebRtc_UWord8)195;
797
798 // Used fixed length of 2
799 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
800 rtcpbuffer[pos++]=(WebRtc_UWord8)(1);
801
802 // Add inter-arrival jitter
803 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
804 jitterTransmissionTimeOffset);
805 pos += 4;
806 return 0;
807}
808
niklase@google.com470e71d2011-07-07 08:21:25 +0000809WebRtc_Word32
810RTCPSender::BuildPLI(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
811{
812 // sanity
813 if(pos + 12 >= IP_PACKET_SIZE)
814 {
815 return -2;
816 }
817 // add picture loss indicator
818 WebRtc_UWord8 FMT = 1;
819 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
820 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
821
822 //Used fixed length of 2
823 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
824 rtcpbuffer[pos++]=(WebRtc_UWord8)(2);
825
826 // Add our own SSRC
827 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
828 pos += 4;
829
830 // Add the remote SSRC
831 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
832 pos += 4;
833 return 0;
834}
835
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000836WebRtc_Word32 RTCPSender::BuildFIR(WebRtc_UWord8* rtcpbuffer,
837 WebRtc_UWord32& pos,
838 bool repeat) {
839 // sanity
840 if(pos + 20 >= IP_PACKET_SIZE) {
841 return -2;
842 }
843 if (!repeat) {
844 _sequenceNumberFIR++; // do not increase if repetition
845 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000846
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000847 // add full intra request indicator
848 WebRtc_UWord8 FMT = 4;
849 rtcpbuffer[pos++] = (WebRtc_UWord8)0x80 + FMT;
850 rtcpbuffer[pos++] = (WebRtc_UWord8)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000851
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000852 //Length of 4
853 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
854 rtcpbuffer[pos++] = (WebRtc_UWord8)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000855
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000856 // Add our own SSRC
857 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
858 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000859
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000860 // RFC 5104 4.3.1.2. Semantics
861 // SSRC of media source
862 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
863 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
864 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
865 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000866
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000867 // Additional Feedback Control Information (FCI)
868 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
869 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000870
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000871 rtcpbuffer[pos++] = (WebRtc_UWord8)(_sequenceNumberFIR);
872 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
873 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
874 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
875 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000876}
877
878/*
879 0 1 2 3
880 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
881 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
882 | First | Number | PictureID |
883 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
884*/
885WebRtc_Word32
886RTCPSender::BuildSLI(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos, const WebRtc_UWord8 pictureID)
887{
888 // sanity
889 if(pos + 16 >= IP_PACKET_SIZE)
890 {
891 return -2;
892 }
893 // add slice loss indicator
894 WebRtc_UWord8 FMT = 2;
895 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
896 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
897
898 //Used fixed length of 3
899 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
900 rtcpbuffer[pos++]=(WebRtc_UWord8)(3);
901
902 // Add our own SSRC
903 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
904 pos += 4;
905
906 // Add the remote SSRC
907 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
908 pos += 4;
909
910 // Add first, number & picture ID 6 bits
911 // first = 0, 13 - bits
912 // number = 0x1fff, 13 - bits only ones for now
913 WebRtc_UWord32 sliField = (0x1fff << 6)+ (0x3f & pictureID);
914 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
915 pos += 4;
916 return 0;
917}
918
919/*
920 0 1 2 3
921 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
922 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
923 | PB |0| Payload Type| Native RPSI bit string |
924 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
925 | defined per codec ... | Padding (0) |
926 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
927*/
928/*
929* Note: not generic made for VP8
930*/
931WebRtc_Word32
932RTCPSender::BuildRPSI(WebRtc_UWord8* rtcpbuffer,
933 WebRtc_UWord32& pos,
934 const WebRtc_UWord64 pictureID,
935 const WebRtc_UWord8 payloadType)
936{
937 // sanity
938 if(pos + 24 >= IP_PACKET_SIZE)
939 {
940 return -2;
941 }
942 // add Reference Picture Selection Indication
943 WebRtc_UWord8 FMT = 3;
944 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
945 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
946
947 // calc length
948 WebRtc_UWord32 bitsRequired = 7;
949 WebRtc_UWord8 bytesRequired = 1;
950 while((pictureID>>bitsRequired) > 0)
951 {
952 bitsRequired += 7;
953 bytesRequired++;
954 }
955
956 WebRtc_UWord8 size = 3;
957 if(bytesRequired > 6)
958 {
959 size = 5;
960 } else if(bytesRequired > 2)
961 {
962 size = 4;
963 }
964 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
965 rtcpbuffer[pos++]=size;
966
967 // Add our own SSRC
968 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
969 pos += 4;
970
971 // Add the remote SSRC
972 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
973 pos += 4;
974
975 // calc padding length
976 WebRtc_UWord8 paddingBytes = 4-((2+bytesRequired)%4);
977 if(paddingBytes == 4)
978 {
979 paddingBytes = 0;
980 }
981 // add padding length in bits
982 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
983 pos++;
984
985 // add payload type
986 rtcpbuffer[pos] = payloadType;
987 pos++;
988
989 // add picture ID
990 for(int i = bytesRequired-1; i > 0; i--)
991 {
992 rtcpbuffer[pos] = 0x80 | WebRtc_UWord8(pictureID >> (i*7));
993 pos++;
994 }
995 // add last byte of picture ID
996 rtcpbuffer[pos] = WebRtc_UWord8(pictureID & 0x7f);
997 pos++;
998
999 // add padding
1000 for(int j = 0; j <paddingBytes; j++)
1001 {
1002 rtcpbuffer[pos] = 0;
1003 pos++;
1004 }
1005 return 0;
1006}
1007
1008WebRtc_Word32
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001009RTCPSender::BuildREMB(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1010{
1011 // sanity
1012 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1013 {
1014 return -2;
1015 }
1016 // add application layer feedback
1017 WebRtc_UWord8 FMT = 15;
1018 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1019 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
1020
1021 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1022 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1023
1024 // Add our own SSRC
1025 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1026 pos += 4;
1027
1028 // Remote SSRC must be 0
1029 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1030 pos += 4;
1031
1032 rtcpbuffer[pos++]='R';
1033 rtcpbuffer[pos++]='E';
1034 rtcpbuffer[pos++]='M';
1035 rtcpbuffer[pos++]='B';
1036
1037 rtcpbuffer[pos++] = _lengthRembSSRC;
1038 // 6 bit Exp
1039 // 18 bit mantissa
1040 WebRtc_UWord8 brExp = 0;
1041 for(WebRtc_UWord32 i=0; i<64; i++)
1042 {
1043 if(_rembBitrate <= ((WebRtc_UWord32)262143 << i))
1044 {
1045 brExp = i;
1046 break;
1047 }
1048 }
1049 const WebRtc_UWord32 brMantissa = (_rembBitrate >> brExp);
1050 rtcpbuffer[pos++]=(WebRtc_UWord8)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1051 rtcpbuffer[pos++]=(WebRtc_UWord8)(brMantissa >> 8);
1052 rtcpbuffer[pos++]=(WebRtc_UWord8)(brMantissa);
1053
1054 for (int i = 0; i < _lengthRembSSRC; i++)
1055 {
1056 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1057 pos += 4;
1058 }
1059 return 0;
1060}
1061
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001062void
1063RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001064{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001065 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001066 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001067}
1068
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001069WebRtc_Word32
1070RTCPSender::BuildTMMBR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001071{
1072 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1073 // If the sender is an owner of the TMMBN -> send TMMBR
1074 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1075
niklase@google.com470e71d2011-07-07 08:21:25 +00001076 // get current bounding set from RTCP receiver
1077 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001078 // store in candidateSet, allocates one extra slot
1079 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001080
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001081 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1082 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1083 // since RTCPreceiver is not doing the reverse we should be fine
1084 WebRtc_Word32 lengthOfBoundingSet
1085 = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001086
1087 if(lengthOfBoundingSet > 0)
1088 {
1089 for (WebRtc_Word32 i = 0; i < lengthOfBoundingSet; i++)
1090 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001091 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1092 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001093 {
1094 // do not send the same tuple
1095 return 0;
1096 }
1097 }
1098 if(!tmmbrOwner)
1099 {
1100 // use received bounding set as candidate set
1101 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001102 candidateSet->SetEntry(lengthOfBoundingSet,
1103 _tmmbr_Send,
1104 _packetOH_Send,
1105 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001106 int numCandidates = lengthOfBoundingSet+ 1;
1107
1108 // find bounding set
1109 TMMBRSet* boundingSet = NULL;
1110 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1111 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1112 {
1113 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1114 }
1115 if(!tmmbrOwner)
1116 {
1117 // did not enter bounding set, no meaning to send this request
1118 return 0;
1119 }
1120 }
1121 }
1122
1123 if(_tmmbr_Send)
1124 {
1125 // sanity
1126 if(pos + 20 >= IP_PACKET_SIZE)
1127 {
1128 return -2;
1129 }
1130 // add TMMBR indicator
1131 WebRtc_UWord8 FMT = 3;
1132 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1133 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1134
1135 //Length of 4
1136 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1137 rtcpbuffer[pos++]=(WebRtc_UWord8)(4);
1138
1139 // Add our own SSRC
1140 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1141 pos += 4;
1142
1143 // RFC 5104 4.2.1.2. Semantics
1144
1145 // SSRC of media source
1146 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1147 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1148 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1149 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1150
1151 // Additional Feedback Control Information (FCI)
1152 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1153 pos += 4;
1154
1155 WebRtc_UWord32 bitRate = _tmmbr_Send*1000;
1156 WebRtc_UWord32 mmbrExp = 0;
1157 for(WebRtc_UWord32 i=0;i<64;i++)
1158 {
1159 if(bitRate <= ((WebRtc_UWord32)131071 << i))
1160 {
1161 mmbrExp = i;
1162 break;
1163 }
1164 }
1165 WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp);
1166
1167 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1168 rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);
1169 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1170 rtcpbuffer[pos++]=(WebRtc_UWord8)(_packetOH_Send);
1171 }
1172 return 0;
1173}
1174
1175WebRtc_Word32
1176RTCPSender::BuildTMMBN(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1177{
1178 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1179 if(boundingSet == NULL)
1180 {
1181 return -1;
1182 }
1183 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001184 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001185 {
1186 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1187 return -2;
1188 }
1189 WebRtc_UWord8 FMT = 4;
1190 // add TMMBN indicator
1191 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1192 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1193
1194 //Add length later
1195 int posLength = pos;
1196 pos++;
1197 pos++;
1198
1199 // Add our own SSRC
1200 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1201 pos += 4;
1202
1203 // RFC 5104 4.2.2.2. Semantics
1204
1205 // SSRC of media source
1206 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1207 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1208 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1209 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1210
1211 // Additional Feedback Control Information (FCI)
1212 int numBoundingSet = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001213 for(WebRtc_UWord32 n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001214 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001215 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001216 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001217 WebRtc_UWord32 tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001218 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1219 pos += 4;
1220
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001221 WebRtc_UWord32 bitRate = boundingSet->Tmmbr(n) * 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001222 WebRtc_UWord32 mmbrExp = 0;
1223 for(int i=0; i<64; i++)
1224 {
1225 if(bitRate <= ((WebRtc_UWord32)131071 << i))
1226 {
1227 mmbrExp = i;
1228 break;
1229 }
1230 }
1231 WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp);
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001232 WebRtc_UWord32 measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001233
1234 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1235 rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);
1236 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1237 rtcpbuffer[pos++]=(WebRtc_UWord8)(measuredOH);
1238 numBoundingSet++;
1239 }
1240 }
1241 WebRtc_UWord16 length= (WebRtc_UWord16)(2+2*numBoundingSet);
1242 rtcpbuffer[posLength++]=(WebRtc_UWord8)(length>>8);
1243 rtcpbuffer[posLength]=(WebRtc_UWord8)(length);
1244 return 0;
1245}
1246
1247WebRtc_Word32
1248RTCPSender::BuildAPP(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1249{
1250 // sanity
1251 if(_appData == NULL)
1252 {
1253 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1254 return -1;
1255 }
1256 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1257 {
1258 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1259 return -2;
1260 }
1261 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + _appSubType;
1262
1263 // Add APP ID
1264 rtcpbuffer[pos++]=(WebRtc_UWord8)204;
1265
1266 WebRtc_UWord16 length = (_appLength>>2) + 2; // include SSRC and name
1267 rtcpbuffer[pos++]=(WebRtc_UWord8)(length>>8);
1268 rtcpbuffer[pos++]=(WebRtc_UWord8)(length);
1269
1270 // Add our own SSRC
1271 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1272 pos += 4;
1273
1274 // Add our application name
1275 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1276 pos += 4;
1277
1278 // Add the data
1279 memcpy(rtcpbuffer +pos, _appData,_appLength);
1280 pos += _appLength;
1281 return 0;
1282}
1283
1284WebRtc_Word32
1285RTCPSender::BuildNACK(WebRtc_UWord8* rtcpbuffer,
1286 WebRtc_UWord32& pos,
1287 const WebRtc_Word32 nackSize,
1288 const WebRtc_UWord16* nackList)
1289{
1290 // sanity
1291 if(pos + 16 >= IP_PACKET_SIZE)
1292 {
1293 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1294 return -2;
1295 }
1296
1297 // int size, WebRtc_UWord16* nackList
1298 // add nack list
1299 WebRtc_UWord8 FMT = 1;
1300 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1301 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1302
1303 rtcpbuffer[pos++]=(WebRtc_UWord8) 0;
1304 int nackSizePos = pos;
1305 rtcpbuffer[pos++]=(WebRtc_UWord8)(3); //setting it to one kNACK signal as default
1306
1307 // Add our own SSRC
1308 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1309 pos += 4;
1310
1311 // Add the remote SSRC
1312 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1313 pos += 4;
1314
1315 // add the list
1316 int i = 0;
1317 int numOfNackFields = 0;
1318 while(nackSize > i && numOfNackFields < 253)
1319 {
1320 WebRtc_UWord16 nack = nackList[i];
1321 // put dow our sequence number
1322 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, nack);
1323 pos += 2;
1324
1325 i++;
1326 numOfNackFields++;
1327 if(nackSize > i)
1328 {
1329 bool moreThan16Away = (WebRtc_UWord16(nack+16) < nackList[i])?true: false;
1330 if(!moreThan16Away)
1331 {
1332 // check for a wrap
1333 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1334 {
1335 // wrap
1336 moreThan16Away = true;
1337 }
1338 }
1339 if(moreThan16Away)
1340 {
1341 // next is more than 16 away
1342 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1343 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1344 } else
1345 {
1346 // build our bitmask
1347 WebRtc_UWord16 bitmask = 0;
1348
1349 bool within16Away = (WebRtc_UWord16(nack+16) > nackList[i])?true: false;
1350 if(within16Away)
1351 {
1352 // check for a wrap
1353 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1354 {
1355 // wrap
1356 within16Away = false;
1357 }
1358 }
1359
1360 while( nackSize > i && within16Away)
1361 {
1362 WebRtc_Word16 shift = (nackList[i]-nack)-1;
1363 assert(!(shift > 15) && !(shift < 0));
1364
1365 bitmask += (1<< shift);
1366 i++;
1367 if(nackSize > i)
1368 {
1369 within16Away = (WebRtc_UWord16(nack+16) > nackList[i])?true: false;
1370 if(within16Away)
1371 {
1372 // check for a wrap
1373 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1374 {
1375 // wrap
1376 within16Away = false;
1377 }
1378 }
1379 }
1380 }
1381 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, bitmask);
1382 pos += 2;
1383 }
1384 // sanity do we have room from one more 4 byte block?
1385 if(pos + 4 >= IP_PACKET_SIZE)
1386 {
1387 return -2;
1388 }
1389 } else
1390 {
1391 // no more in the list
1392 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1393 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1394 }
1395 }
1396 rtcpbuffer[nackSizePos]=(WebRtc_UWord8)(2+numOfNackFields);
1397 return 0;
1398}
1399
1400WebRtc_Word32
1401RTCPSender::BuildBYE(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1402{
1403 // sanity
1404 if(pos + 8 >= IP_PACKET_SIZE)
1405 {
1406 return -2;
1407 }
1408 if(_includeCSRCs)
1409 {
1410 // Add a bye packet
1411 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1412 rtcpbuffer[pos++]=(WebRtc_UWord8)203;
1413
1414 // length
1415 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1416 rtcpbuffer[pos++]=(WebRtc_UWord8)(1 + _CSRCs);
1417
1418 // Add our own SSRC
1419 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1420 pos += 4;
1421
1422 // add CSRCs
1423 for(int i = 0; i < _CSRCs; i++)
1424 {
1425 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1426 pos += 4;
1427 }
1428 } else
1429 {
1430 // Add a bye packet
1431 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1; // number of SSRC+CSRCs
1432 rtcpbuffer[pos++]=(WebRtc_UWord8)203;
1433
1434 // length
1435 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1436 rtcpbuffer[pos++]=(WebRtc_UWord8)1;
1437
1438 // Add our own SSRC
1439 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1440 pos += 4;
1441 }
1442 return 0;
1443}
1444
1445WebRtc_Word32
1446RTCPSender::BuildVoIPMetric(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1447{
1448 // sanity
1449 if(pos + 44 >= IP_PACKET_SIZE)
1450 {
1451 return -2;
1452 }
1453
1454 // Add XR header
1455 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
1456 rtcpbuffer[pos++]=(WebRtc_UWord8)207;
1457
1458 WebRtc_UWord32 XRLengthPos = pos;
1459
1460 // handle length later on
1461 pos++;
1462 pos++;
1463
1464 // Add our own SSRC
1465 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1466 pos += 4;
1467
1468 // Add a VoIP metrics block
1469 rtcpbuffer[pos++]=7;
1470 rtcpbuffer[pos++]=0;
1471 rtcpbuffer[pos++]=0;
1472 rtcpbuffer[pos++]=8;
1473
1474 // Add the remote SSRC
1475 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1476 pos += 4;
1477
1478 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1479 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1480 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1481 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1482
1483 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.burstDuration >> 8);
1484 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.burstDuration);
1485 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.gapDuration >> 8);
1486 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.gapDuration);
1487
1488 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.roundTripDelay >> 8);
1489 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.roundTripDelay);
1490 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.endSystemDelay >> 8);
1491 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.endSystemDelay);
1492
1493 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1494 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1495 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1496 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1497
1498 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1499 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1500 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1501 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1502
1503 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1504 rtcpbuffer[pos++] = 0; // reserved
1505 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBnominal >> 8);
1506 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBnominal);
1507
1508 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBmax >> 8);
1509 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBmax);
1510 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBabsMax >> 8);
1511 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBabsMax);
1512
1513 rtcpbuffer[XRLengthPos]=(WebRtc_UWord8)(0);
1514 rtcpbuffer[XRLengthPos+1]=(WebRtc_UWord8)(10);
1515 return 0;
1516}
1517
1518WebRtc_Word32
1519RTCPSender::SendRTCP(const WebRtc_UWord32 packetTypeFlags,
1520 const WebRtc_Word32 nackSize, // NACK
1521 const WebRtc_UWord16* nackList, // NACK
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001522 const bool repeat, // FIR
niklase@google.com470e71d2011-07-07 08:21:25 +00001523 const WebRtc_UWord64 pictureID) // SLI & RPSI
1524{
1525 WebRtc_UWord32 rtcpPacketTypeFlags = packetTypeFlags;
1526 WebRtc_UWord32 pos = 0;
1527 WebRtc_UWord8 rtcpbuffer[IP_PACKET_SIZE];
1528
niklase@google.com470e71d2011-07-07 08:21:25 +00001529 do // only to be able to use break :) (and the critsect must be inside its own scope)
1530 {
1531 // collect the received information
1532 RTCPReportBlock received;
1533 bool hasReceived = false;
1534 WebRtc_UWord32 NTPsec = 0;
1535 WebRtc_UWord32 NTPfrac = 0;
xians@webrtc.org8738d272011-11-25 13:43:53 +00001536 bool rtcpCompound = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001537 WebRtc_UWord32 jitterTransmissionOffset = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001538
xians@webrtc.org8738d272011-11-25 13:43:53 +00001539 {
1540 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1541 if(_method == kRtcpOff)
1542 {
1543 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1544 "%s invalid state", __FUNCTION__);
1545 return -1;
1546 }
1547 rtcpCompound = (_method == kRtcpCompound) ? true : false;
1548 }
1549
1550 if (rtcpCompound ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001551 rtcpPacketTypeFlags & kRtcpReport ||
1552 rtcpPacketTypeFlags & kRtcpSr ||
1553 rtcpPacketTypeFlags & kRtcpRr)
1554 {
1555 // get statistics from our RTPreceiver outside critsect
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001556 if(_rtpRtcp.ReportBlockStatistics(&received.fractionLost,
1557 &received.cumulativeLost,
1558 &received.extendedHighSeqNum,
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001559 &received.jitter,
1560 &jitterTransmissionOffset) == 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001561 {
1562 hasReceived = true;
1563
1564 WebRtc_UWord32 lastReceivedRRNTPsecs = 0;
1565 WebRtc_UWord32 lastReceivedRRNTPfrac = 0;
1566 WebRtc_UWord32 remoteSR = 0;
1567
1568 // ok even if we have not received a SR, we will send 0 in that case
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001569 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1570 lastReceivedRRNTPfrac,
1571 remoteSR);
niklase@google.com470e71d2011-07-07 08:21:25 +00001572
1573 // get our NTP as late as possible to avoid a race
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001574 _clock.CurrentNTP(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001575
1576 // Delay since last received report
1577 WebRtc_UWord32 delaySinceLastReceivedSR = 0;
1578 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
1579 {
1580 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1581 WebRtc_UWord32 now=NTPsec&0x0000FFFF;
1582 now <<=16;
1583 now += (NTPfrac&0xffff0000)>>16;
1584
1585 WebRtc_UWord32 receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
1586 receiveTime <<=16;
1587 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1588
1589 delaySinceLastReceivedSR = now-receiveTime;
1590 }
1591 received.delaySinceLastSR = delaySinceLastReceivedSR;
1592 received.lastSR = remoteSR;
1593 } else
1594 {
1595 // we need to send our NTP even if we dont have received any reports
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001596 _clock.CurrentNTP(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001597 }
1598 }
1599
1600 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1601
1602 if(_TMMBR ) // attach TMMBR to send and receive reports
1603 {
1604 rtcpPacketTypeFlags |= kRtcpTmmbr;
1605 }
1606 if(_appSend)
1607 {
1608 rtcpPacketTypeFlags |= kRtcpApp;
1609 _appSend = false;
1610 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001611 if(_REMB && _sendREMB)
1612 {
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +00001613 // Always attach REMB to SR if that is configured. Note that REMB is
1614 // only sent on one of the RTP modules in the REMB group.
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001615 rtcpPacketTypeFlags |= kRtcpRemb;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001616 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001617 if(_xrSendVoIPMetric)
1618 {
1619 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1620 _xrSendVoIPMetric = false;
1621 }
1622 if(_sendTMMBN) // set when having received a TMMBR
1623 {
1624 rtcpPacketTypeFlags |= kRtcpTmmbn;
1625 _sendTMMBN = false;
1626 }
1627
1628 if(_method == kRtcpCompound)
1629 {
1630 if(_sending)
1631 {
1632 rtcpPacketTypeFlags |= kRtcpSr;
1633 } else
1634 {
1635 rtcpPacketTypeFlags |= kRtcpRr;
1636 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001637 if (_IJ && hasReceived)
1638 {
1639 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1640 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001641 } else if(_method == kRtcpNonCompound)
1642 {
1643 if(rtcpPacketTypeFlags & kRtcpReport)
1644 {
1645 if(_sending)
1646 {
1647 rtcpPacketTypeFlags |= kRtcpSr;
1648 } else
1649 {
1650 rtcpPacketTypeFlags |= kRtcpRr;
1651 }
1652 }
1653 }
1654 if( rtcpPacketTypeFlags & kRtcpRr ||
1655 rtcpPacketTypeFlags & kRtcpSr)
1656 {
1657 // generate next time to send a RTCP report
1658 // seeded from RTP constructor
1659 WebRtc_Word32 random = rand() % 1000;
1660 WebRtc_Word32 timeToNext = RTCP_INTERVAL_AUDIO_MS;
1661
1662 if(_audio)
1663 {
1664 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
1665 }else
1666 {
1667 WebRtc_UWord32 minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1668 if(_sending)
1669 {
1670 // calc bw for video 360/sendBW in kbit/s
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001671 WebRtc_UWord32 sendBitrateKbit = 0;
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001672 WebRtc_UWord32 videoRate = 0;
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001673 WebRtc_UWord32 fecRate = 0;
1674 WebRtc_UWord32 nackRate = 0;
1675 _rtpRtcp.BitrateSent(&sendBitrateKbit,
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001676 &videoRate,
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001677 &fecRate,
1678 &nackRate);
1679 sendBitrateKbit /= 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001680 if(sendBitrateKbit != 0)
1681 {
1682 minIntervalMs = 360000/sendBitrateKbit;
1683 }
1684 }
1685 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1686 {
1687 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1688 }
1689 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1690 }
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001691 _nextTimeToSendRTCP = _clock.GetTimeInMS() + timeToNext;
niklase@google.com470e71d2011-07-07 08:21:25 +00001692 }
1693
1694 // if the data does not fitt in the packet we fill it as much as possible
1695 WebRtc_Word32 buildVal = 0;
1696
1697 if(rtcpPacketTypeFlags & kRtcpSr)
1698 {
1699 if(hasReceived)
1700 {
1701 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
1702 } else
1703 {
1704 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac);
1705 }
1706 if(buildVal == -1)
1707 {
1708 return -1; // error
1709
1710 }else if(buildVal == -2)
1711 {
1712 break; // out of buffer
1713 }
1714 buildVal = BuildSDEC(rtcpbuffer, pos);
1715 if(buildVal == -1)
1716 {
1717 return -1; // error
1718
1719 }else if(buildVal == -2)
1720 {
1721 break; // out of buffer
1722 }
1723
1724 }else if(rtcpPacketTypeFlags & kRtcpRr)
1725 {
1726 if(hasReceived)
1727 {
1728 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
1729 }else
1730 {
1731 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
1732 }
1733 if(buildVal == -1)
1734 {
1735 return -1; // error
1736
1737 }else if(buildVal == -2)
1738 {
1739 break; // out of buffer
1740 }
1741 // only of set
1742 if(_CNAME[0] != 0)
1743 {
1744 buildVal = BuildSDEC(rtcpbuffer, pos);
1745 if(buildVal == -1)
1746 {
1747 return -1; // error
1748 }
1749 }
1750 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001751 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1752 {
1753 // If present, this RTCP packet must be placed after a
1754 // receiver report.
1755 buildVal = BuildExtendedJitterReport(rtcpbuffer,
1756 pos,
1757 jitterTransmissionOffset);
1758 if(buildVal == -1)
1759 {
1760 return -1; // error
1761 }
1762 else if(buildVal == -2)
1763 {
1764 break; // out of buffer
1765 }
1766 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001767 if(rtcpPacketTypeFlags & kRtcpPli)
1768 {
1769 buildVal = BuildPLI(rtcpbuffer, pos);
1770 if(buildVal == -1)
1771 {
1772 return -1; // error
1773
1774 }else if(buildVal == -2)
1775 {
1776 break; // out of buffer
1777 }
1778 }
1779 if(rtcpPacketTypeFlags & kRtcpFir)
1780 {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001781 buildVal = BuildFIR(rtcpbuffer, pos, repeat);
niklase@google.com470e71d2011-07-07 08:21:25 +00001782 if(buildVal == -1)
1783 {
1784 return -1; // error
1785
1786 }else if(buildVal == -2)
1787 {
1788 break; // out of buffer
1789 }
1790 }
1791 if(rtcpPacketTypeFlags & kRtcpSli)
1792 {
1793 buildVal = BuildSLI(rtcpbuffer, pos, (WebRtc_UWord8)pictureID);
1794 if(buildVal == -1)
1795 {
1796 return -1; // error
1797
1798 }else if(buildVal == -2)
1799 {
1800 break; // out of buffer
1801 }
1802 }
1803 if(rtcpPacketTypeFlags & kRtcpRpsi)
1804 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001805 const WebRtc_Word8 payloadType = _rtpRtcp.SendPayloadType();
niklase@google.com470e71d2011-07-07 08:21:25 +00001806 if(payloadType == -1)
1807 {
1808 return -1;
1809 }
1810 buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (WebRtc_UWord8)payloadType);
1811 if(buildVal == -1)
1812 {
1813 return -1; // error
1814
1815 }else if(buildVal == -2)
1816 {
1817 break; // out of buffer
1818 }
1819 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001820 if(rtcpPacketTypeFlags & kRtcpRemb)
1821 {
1822 buildVal = BuildREMB(rtcpbuffer, pos);
1823 if(buildVal == -1)
1824 {
1825 return -1; // error
1826
1827 }else if(buildVal == -2)
1828 {
1829 break; // out of buffer
1830 }
1831 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001832 if(rtcpPacketTypeFlags & kRtcpBye)
1833 {
1834 buildVal = BuildBYE(rtcpbuffer, pos);
1835 if(buildVal == -1)
1836 {
1837 return -1; // error
1838
1839 }else if(buildVal == -2)
1840 {
1841 break; // out of buffer
1842 }
1843 }
1844 if(rtcpPacketTypeFlags & kRtcpApp)
1845 {
1846 buildVal = BuildAPP(rtcpbuffer, pos);
1847 if(buildVal == -1)
1848 {
1849 return -1; // error
1850
1851 }else if(buildVal == -2)
1852 {
1853 break; // out of buffer
1854 }
1855 }
1856 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1857 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001858 buildVal = BuildTMMBR(rtcpbuffer, pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001859 if(buildVal == -1)
1860 {
1861 return -1; // error
1862
1863 }else if(buildVal == -2)
1864 {
1865 break; // out of buffer
1866 }
1867 }
1868 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1869 {
1870 buildVal = BuildTMMBN(rtcpbuffer, pos);
1871 if(buildVal == -1)
1872 {
1873 return -1; // error
1874
1875 }else if(buildVal == -2)
1876 {
1877 break; // out of buffer
1878 }
1879 }
1880 if(rtcpPacketTypeFlags & kRtcpNack)
1881 {
1882 buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList);
1883 if(buildVal == -1)
1884 {
1885 return -1; // error
1886
1887 }else if(buildVal == -2)
1888 {
1889 break; // out of buffer
1890 }
1891 }
1892 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1893 {
1894 buildVal = BuildVoIPMetric(rtcpbuffer, pos);
1895 if(buildVal == -1)
1896 {
1897 return -1; // error
1898
1899 }else if(buildVal == -2)
1900 {
1901 break; // out of buffer
1902 }
1903 }
1904 }while (false);
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001905 // Sanity don't send empty packets.
1906 if (pos == 0)
1907 {
1908 return -1;
1909 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001910 return SendToNetwork(rtcpbuffer, (WebRtc_UWord16)pos);
1911}
1912
1913WebRtc_Word32
1914RTCPSender::SendToNetwork(const WebRtc_UWord8* dataBuffer,
1915 const WebRtc_UWord16 length)
1916{
1917 CriticalSectionScoped lock(_criticalSectionTransport);
1918 if(_cbTransport)
1919 {
1920 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1921 {
1922 return 0;
1923 }
1924 }
1925 return -1;
1926}
1927
1928WebRtc_Word32
1929RTCPSender::SetCSRCStatus(const bool include)
1930{
1931 _includeCSRCs = include;
1932 return 0;
1933}
1934
1935WebRtc_Word32
1936RTCPSender::SetCSRCs(const WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize],
1937 const WebRtc_UWord8 arrLength)
1938{
1939 if(arrLength > kRtpCsrcSize)
1940 {
1941 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1942 assert(false);
1943 return -1;
1944 }
1945
1946 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1947
1948 for(int i = 0; i < arrLength;i++)
1949 {
1950 _CSRC[i] = arrOfCSRC[i];
1951 }
1952 _CSRCs = arrLength;
1953 return 0;
1954}
1955
1956WebRtc_Word32
1957RTCPSender::SetApplicationSpecificData(const WebRtc_UWord8 subType,
1958 const WebRtc_UWord32 name,
1959 const WebRtc_UWord8* data,
1960 const WebRtc_UWord16 length)
1961{
1962 if(length %4 != 0)
1963 {
1964 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1965 return -1;
1966 }
1967 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1968
1969 if(_appData)
1970 {
1971 delete [] _appData;
1972 }
1973
1974 _appSend = true;
1975 _appSubType = subType;
1976 _appName = name;
1977 _appData = new WebRtc_UWord8[length];
1978 _appLength = length;
1979 memcpy(_appData, data, length);
1980 return 0;
1981}
1982
1983WebRtc_Word32
1984RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
1985{
1986 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1987 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
1988
1989 _xrSendVoIPMetric = true;
1990 return 0;
1991}
1992
1993// called under critsect _criticalSectionRTCPSender
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001994WebRtc_Word32 RTCPSender::AddReportBlocks(WebRtc_UWord8* rtcpbuffer,
1995 WebRtc_UWord32& pos,
1996 WebRtc_UWord8& numberOfReportBlocks,
1997 const RTCPReportBlock* received,
1998 const WebRtc_UWord32 NTPsec,
1999 const WebRtc_UWord32 NTPfrac) {
2000 // sanity one block
2001 if(pos + 24 >= IP_PACKET_SIZE) {
2002 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2003 "%s invalid argument", __FUNCTION__);
2004 return -1;
2005 }
2006 numberOfReportBlocks = _reportBlocks.size();
2007 if (received) {
2008 // add our multiple RR to numberOfReportBlocks
2009 numberOfReportBlocks++;
2010 }
2011 if (received) {
2012 // answer to the one that sends to me
2013 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac);
2014
2015 // Remote SSRC
2016 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
2017 pos += 4;
2018
2019 // fraction lost
2020 rtcpbuffer[pos++]=received->fractionLost;
2021
2022 // cumulative loss
2023 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2024 received->cumulativeLost);
2025 pos += 3;
2026 // extended highest seq_no, contain the highest sequence number received
2027 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2028 received->extendedHighSeqNum);
2029 pos += 4;
2030
2031 //Jitter
2032 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
2033 pos += 4;
2034
2035 // Last SR timestamp, our NTP time when we received the last report
2036 // This is the value that we read from the send report packet not when we
2037 // received it...
2038 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
2039 pos += 4;
2040
2041 // Delay since last received report,time since we received the report
2042 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2043 received->delaySinceLastSR);
2044 pos += 4;
2045 }
2046 if ((pos + _reportBlocks.size() * 24) >= IP_PACKET_SIZE) {
2047 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2048 "%s invalid argument", __FUNCTION__);
2049 return -1;
2050 }
2051 std::map<WebRtc_UWord32, RTCPReportBlock*>::iterator it =
2052 _reportBlocks.begin();
2053
2054 for (; it != _reportBlocks.end(); it++) {
2055 // we can have multiple report block in a conference
2056 WebRtc_UWord32 remoteSSRC = it->first;
2057 RTCPReportBlock* reportBlock = it->second;
2058 if (reportBlock) {
2059 // Remote SSRC
2060 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
2061 pos += 4;
2062
2063 // fraction lost
2064 rtcpbuffer[pos++] = reportBlock->fractionLost;
2065
2066 // cumulative loss
2067 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2068 reportBlock->cumulativeLost);
2069 pos += 3;
2070
2071 // extended highest seq_no, contain the highest sequence number received
2072 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2073 reportBlock->extendedHighSeqNum);
2074 pos += 4;
2075
2076 //Jitter
2077 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2078 reportBlock->jitter);
2079 pos += 4;
2080
2081 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2082 reportBlock->lastSR);
2083 pos += 4;
2084
2085 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2086 reportBlock->delaySinceLastSR);
2087 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002088 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002089 }
2090 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00002091}
2092
2093// no callbacks allowed inside this function
2094WebRtc_Word32
2095RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
2096 const WebRtc_UWord32 maxBitrateKbit)
2097{
2098 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2099
2100 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2101 {
2102 _sendTMMBN = true;
2103 return 0;
2104 }
2105 return -1;
2106}
niklase@google.com470e71d2011-07-07 08:21:25 +00002107} // namespace webrtc