blob: eb3a905d99d43005e78f94696eb02397509ed35c [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/remote_bitrate_estimator/remote_rate_control.h"
19#include "modules/rtp_rtcp/source/rtp_rtcp_impl.h"
20#include "system_wrappers/interface/critical_section_wrapper.h"
21#include "system_wrappers/interface/trace.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000022
niklase@google.com470e71d2011-07-07 08:21:25 +000023namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000024
25using RTCPUtility::RTCPCnameInformation;
26
niklase@google.com470e71d2011-07-07 08:21:25 +000027RTCPSender::RTCPSender(const WebRtc_Word32 id,
28 const bool audio,
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000029 RtpRtcpClock* clock,
pwestin@webrtc.org741da942011-09-20 13:52:04 +000030 ModuleRtpRtcpImpl* owner) :
niklase@google.com470e71d2011-07-07 08:21:25 +000031 _id(id),
32 _audio(audio),
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000033 _clock(*clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000034 _method(kRtcpOff),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000035 _rtpRtcp(*owner),
henrike@webrtc.org65573f22011-12-13 19:17:27 +000036 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000037 _cbTransport(NULL),
38
henrike@webrtc.org65573f22011-12-13 19:17:27 +000039 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000040 _usingNack(false),
41 _sending(false),
42 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000043 _REMB(false),
44 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000045 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +000046 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000047 _nextTimeToSendRTCP(0),
48 _SSRC(0),
49 _remoteSSRC(0),
50 _CNAME(),
51 _reportBlocks(),
52 _csrcCNAMEs(),
53
54 _cameraDelayMS(0),
55
56 _lastSendReport(),
57 _lastRTCPTime(),
58
59 _CSRCs(0),
60 _CSRC(),
61 _includeCSRCs(true),
62
63 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000064
pwestin@webrtc.org741da942011-09-20 13:52:04 +000065 _lengthRembSSRC(0),
66 _sizeRembSSRC(0),
67 _rembSSRC(NULL),
68 _rembBitrate(0),
69
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000070 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +000071 _tmmbr_Send(0),
72 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000073
74 _appSend(false),
75 _appSubType(0),
76 _appName(),
77 _appData(NULL),
78 _appLength(0),
79 _xrSendVoIPMetric(false),
80 _xrVoIPMetric()
81{
82 memset(_CNAME, 0, sizeof(_CNAME));
83 memset(_lastSendReport, 0, sizeof(_lastSendReport));
84 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
85
86 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
87}
88
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000089RTCPSender::~RTCPSender() {
90 delete [] _rembSSRC;
91 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +000092
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000093 while (!_reportBlocks.empty()) {
94 std::map<WebRtc_UWord32, RTCPReportBlock*>::iterator it =
95 _reportBlocks.begin();
96 delete it->second;
97 _reportBlocks.erase(it);
98 }
99 while (!_csrcCNAMEs.empty()) {
100 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator it =
101 _csrcCNAMEs.begin();
102 delete it->second;
103 _csrcCNAMEs.erase(it);
104 }
105 delete _criticalSectionTransport;
106 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000107
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000108 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000109}
110
111WebRtc_Word32
112RTCPSender::Init()
113{
114 CriticalSectionScoped lock(_criticalSectionRTCPSender);
115
116 _method = kRtcpOff;
117 _cbTransport = NULL;
118 _usingNack = false;
119 _sending = false;
120 _sendTMMBN = false;
121 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000122 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000123 _REMB = false;
124 _sendREMB = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000125 _SSRC = 0;
126 _remoteSSRC = 0;
127 _cameraDelayMS = 0;
128 _sequenceNumberFIR = 0;
129 _tmmbr_Send = 0;
130 _packetOH_Send = 0;
stefan@webrtc.org9354cc92012-06-07 08:10:14 +0000131 //_remoteRateControl.Reset();
niklase@google.com470e71d2011-07-07 08:21:25 +0000132 _nextTimeToSendRTCP = 0;
133 _CSRCs = 0;
134 _appSend = false;
135 _appSubType = 0;
136
137 if(_appData)
138 {
139 delete [] _appData;
140 _appData = NULL;
141 }
142 _appLength = 0;
143
144 _xrSendVoIPMetric = false;
145
146 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
147 memset(_CNAME, 0, sizeof(_CNAME));
148 memset(_lastSendReport, 0, sizeof(_lastSendReport));
149 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
150 return 0;
151}
152
153void
154RTCPSender::ChangeUniqueId(const WebRtc_Word32 id)
155{
156 _id = id;
157}
158
159WebRtc_Word32
160RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
161{
162 CriticalSectionScoped lock(_criticalSectionTransport);
163 _cbTransport = outgoingTransport;
164 return 0;
165}
166
167RTCPMethod
168RTCPSender::Status() const
169{
170 CriticalSectionScoped lock(_criticalSectionRTCPSender);
171 return _method;
172}
173
174WebRtc_Word32
175RTCPSender::SetRTCPStatus(const RTCPMethod method)
176{
177 CriticalSectionScoped lock(_criticalSectionRTCPSender);
178 if(method != kRtcpOff)
179 {
180 if(_audio)
181 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000182 _nextTimeToSendRTCP = _clock.GetTimeInMS() + (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000183 } else
184 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000185 _nextTimeToSendRTCP = _clock.GetTimeInMS() + (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000186 }
187 }
188 _method = method;
189 return 0;
190}
191
192bool
193RTCPSender::Sending() const
194{
195 CriticalSectionScoped lock(_criticalSectionRTCPSender);
196 return _sending;
197}
198
199WebRtc_Word32
200RTCPSender::SetSendingStatus(const bool sending)
201{
202 bool sendRTCPBye = false;
203 {
204 CriticalSectionScoped lock(_criticalSectionRTCPSender);
205
206 if(_method != kRtcpOff)
207 {
208 if(sending == false && _sending == true)
209 {
210 // Trigger RTCP bye
211 sendRTCPBye = true;
212 }
213 }
214 _sending = sending;
215 }
216 if(sendRTCPBye)
217 {
218 return SendRTCP(kRtcpBye);
219 }
220 return 0;
221}
222
223bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000224RTCPSender::REMB() const
225{
226 CriticalSectionScoped lock(_criticalSectionRTCPSender);
227 return _REMB;
228}
229
230WebRtc_Word32
231RTCPSender::SetREMBStatus(const bool enable)
232{
233 CriticalSectionScoped lock(_criticalSectionRTCPSender);
234 _REMB = enable;
235 return 0;
236}
237
238WebRtc_Word32
239RTCPSender::SetREMBData(const WebRtc_UWord32 bitrate,
240 const WebRtc_UWord8 numberOfSSRC,
241 const WebRtc_UWord32* SSRC)
242{
243 CriticalSectionScoped lock(_criticalSectionRTCPSender);
244 _rembBitrate = bitrate;
245
246 if(_sizeRembSSRC < numberOfSSRC)
247 {
248 delete [] _rembSSRC;
249 _rembSSRC = new WebRtc_UWord32[numberOfSSRC];
250 _sizeRembSSRC = numberOfSSRC;
251 }
252
253 _lengthRembSSRC = numberOfSSRC;
254 for (int i = 0; i < numberOfSSRC; i++)
255 {
256 _rembSSRC[i] = SSRC[i];
257 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000258 _sendREMB = true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000259 return 0;
260}
261
262bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000263RTCPSender::TMMBR() const
264{
265 CriticalSectionScoped lock(_criticalSectionRTCPSender);
266 return _TMMBR;
267}
268
269WebRtc_Word32
270RTCPSender::SetTMMBRStatus(const bool enable)
271{
272 CriticalSectionScoped lock(_criticalSectionRTCPSender);
273 _TMMBR = enable;
274 return 0;
275}
276
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000277bool
278RTCPSender::IJ() const
279{
280 CriticalSectionScoped lock(_criticalSectionRTCPSender);
281 return _IJ;
282}
283
284WebRtc_Word32
285RTCPSender::SetIJStatus(const bool enable)
286{
287 CriticalSectionScoped lock(_criticalSectionRTCPSender);
288 _IJ = enable;
289 return 0;
290}
291
niklase@google.com470e71d2011-07-07 08:21:25 +0000292void
293RTCPSender::SetSSRC( const WebRtc_UWord32 ssrc)
294{
295 CriticalSectionScoped lock(_criticalSectionRTCPSender);
296
297 if(_SSRC != 0)
298 {
299 // not first SetSSRC, probably due to a collision
300 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000301 // make sure that we send a RTP packet
302 _nextTimeToSendRTCP = _clock.GetTimeInMS() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000303 }
304 _SSRC = ssrc;
305}
306
307WebRtc_Word32
308RTCPSender::SetRemoteSSRC( const WebRtc_UWord32 ssrc)
309{
310 CriticalSectionScoped lock(_criticalSectionRTCPSender);
311 _remoteSSRC = ssrc;
stefan@webrtc.org9354cc92012-06-07 08:10:14 +0000312 //_remoteRateControl.Reset();
niklase@google.com470e71d2011-07-07 08:21:25 +0000313 return 0;
314}
315
316WebRtc_Word32
317RTCPSender::SetCameraDelay(const WebRtc_Word32 delayMS)
318{
319 CriticalSectionScoped lock(_criticalSectionRTCPSender);
320 if(delayMS > 1000 || delayMS < -1000)
321 {
322 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
323 return -1;
324 }
325 _cameraDelayMS = delayMS;
326 return 0;
327}
328
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000329WebRtc_Word32 RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
330 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000331 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000332 cName[RTCP_CNAME_SIZE - 1] = 0;
333 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000334 return 0;
335}
336
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000337WebRtc_Word32 RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000338 if (!cName)
339 return -1;
340
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000341 CriticalSectionScoped lock(_criticalSectionRTCPSender);
342 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
343 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
344 return 0;
345}
346
347WebRtc_Word32 RTCPSender::AddMixedCNAME(const WebRtc_UWord32 SSRC,
348 const char cName[RTCP_CNAME_SIZE]) {
349 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000350 CriticalSectionScoped lock(_criticalSectionRTCPSender);
351 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
352 return -1;
353 }
354 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000355 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
356 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000357 _csrcCNAMEs[SSRC] = ptr;
358 return 0;
359}
360
361WebRtc_Word32 RTCPSender::RemoveMixedCNAME(const WebRtc_UWord32 SSRC) {
362 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000363 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator it =
364 _csrcCNAMEs.find(SSRC);
365
366 if (it == _csrcCNAMEs.end()) {
367 return -1;
368 }
369 delete it->second;
370 _csrcCNAMEs.erase(it);
371 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000372}
373
374bool
375RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
376{
377/*
378 For audio we use a fix 5 sec interval
379
380 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
381 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
382
383
384From RFC 3550
385
386 MAX RTCP BW is 5% if the session BW
387 A send report is approximately 65 bytes inc CNAME
388 A report report is approximately 28 bytes
389
390 The RECOMMENDED value for the reduced minimum in seconds is 360
391 divided by the session bandwidth in kilobits/second. This minimum
392 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
393
394 If the participant has not yet sent an RTCP packet (the variable
395 initial is true), the constant Tmin is set to 2.5 seconds, else it
396 is set to 5 seconds.
397
398 The interval between RTCP packets is varied randomly over the
399 range [0.5,1.5] times the calculated interval to avoid unintended
400 synchronization of all participants
401
402 if we send
403 If the participant is a sender (we_sent true), the constant C is
404 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
405 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
406 number of senders.
407
408 if we receive only
409 If we_sent is not true, the constant C is set
410 to the average RTCP packet size divided by 75% of the RTCP
411 bandwidth. The constant n is set to the number of receivers
412 (members - senders). If the number of senders is greater than
413 25%, senders and receivers are treated together.
414
415 reconsideration NOT required for peer-to-peer
416 "timer reconsideration" is
417 employed. This algorithm implements a simple back-off mechanism
418 which causes users to hold back RTCP packet transmission if the
419 group sizes are increasing.
420
421 n = number of members
422 C = avg_size/(rtcpBW/4)
423
424 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
425
426 4. The calculated interval T is set to a number uniformly distributed
427 between 0.5 and 1.5 times the deterministic calculated interval.
428
429 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
430 for the fact that the timer reconsideration algorithm converges to
431 a value of the RTCP bandwidth below the intended average
432*/
433
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000434 WebRtc_UWord32 now = _clock.GetTimeInMS();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000435
436 CriticalSectionScoped lock(_criticalSectionRTCPSender);
437
niklase@google.com470e71d2011-07-07 08:21:25 +0000438 if(_method == kRtcpOff)
439 {
440 return false;
441 }
442
niklase@google.com470e71d2011-07-07 08:21:25 +0000443 if(!_audio && sendKeyframeBeforeRTP)
444 {
445 // for video key-frames we want to send the RTCP before the large key-frame
446 // if we have a 100 ms margin
447 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
448 }
449
450 if(now > _nextTimeToSendRTCP)
451 {
452 return true;
453
454 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
455 {
456 // wrap
457 return true;
458 }
459 return false;
460}
461
462WebRtc_UWord32
463RTCPSender::LastSendReport( WebRtc_UWord32& lastRTCPTime)
464{
465 CriticalSectionScoped lock(_criticalSectionRTCPSender);
466
467 lastRTCPTime = _lastRTCPTime[0];
468 return _lastSendReport[0];
469}
470
471WebRtc_UWord32
472RTCPSender::SendTimeOfSendReport(const WebRtc_UWord32 sendReport)
473{
474 CriticalSectionScoped lock(_criticalSectionRTCPSender);
475
476 // This is only saved when we are the sender
477 if((_lastSendReport[0] == 0) || (sendReport == 0))
478 {
479 return 0; // will be ignored
480 } else
481 {
482 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
483 {
484 if( _lastSendReport[i] == sendReport)
485 {
486 return _lastRTCPTime[i];
487 }
488 }
489 }
490 return 0;
491}
492
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000493WebRtc_Word32 RTCPSender::AddReportBlock(const WebRtc_UWord32 SSRC,
494 const RTCPReportBlock* reportBlock) {
495 if (reportBlock == NULL) {
496 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
497 "%s invalid argument", __FUNCTION__);
498 return -1;
499 }
500 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000501
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000502 if (_reportBlocks.size() >= RTCP_MAX_REPORT_BLOCKS) {
503 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
504 "%s invalid argument", __FUNCTION__);
505 return -1;
506 }
507 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
508 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
509 _reportBlocks[SSRC] = copyReportBlock;
510 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000511}
512
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000513WebRtc_Word32 RTCPSender::RemoveReportBlock(const WebRtc_UWord32 SSRC) {
514 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000515
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000516 std::map<WebRtc_UWord32, RTCPReportBlock*>::iterator it =
517 _reportBlocks.find(SSRC);
518
519 if (it == _reportBlocks.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000520 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000521 }
522 delete it->second;
523 _reportBlocks.erase(it);
524 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000525}
526
527WebRtc_Word32
528RTCPSender::BuildSR(WebRtc_UWord8* rtcpbuffer,
529 WebRtc_UWord32& pos,
530 const WebRtc_UWord32 NTPsec,
531 const WebRtc_UWord32 NTPfrac,
532 const RTCPReportBlock* received)
533{
534 // sanity
535 if(pos + 52 >= IP_PACKET_SIZE)
536 {
537 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
538 return -2;
539 }
540 WebRtc_UWord32 RTPtime;
541 WebRtc_UWord32 BackTimedNTPsec;
542 WebRtc_UWord32 BackTimedNTPfrac;
543
544 WebRtc_UWord32 posNumberOfReportBlocks = pos;
545 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
546
547 // Sender report
548 rtcpbuffer[pos++]=(WebRtc_UWord8)200;
549
550 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
551 {
552 // shift old
553 _lastSendReport[i+1] = _lastSendReport[i];
554 _lastRTCPTime[i+1] =_lastRTCPTime[i];
555 }
556
557 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac); // before video cam compensation
558
559 if(_cameraDelayMS >= 0)
560 {
561 // fraction of a second as an unsigned word32 4.294 967 296E9
562 WebRtc_UWord32 cameraDelayFixFrac = (WebRtc_UWord32)_cameraDelayMS* 4294967; // note camera delay can't be larger than +/-1000ms
563 if(NTPfrac > cameraDelayFixFrac)
564 {
565 // no problem just reduce the fraction part
566 BackTimedNTPfrac = NTPfrac - cameraDelayFixFrac;
567 BackTimedNTPsec = NTPsec;
568 } else
569 {
570 // we need to reduce the sec and add that sec to the frac
571 BackTimedNTPsec = NTPsec - 1;
572 BackTimedNTPfrac = 0xffffffff - (cameraDelayFixFrac - NTPfrac);
573 }
574 } else
575 {
576 // fraction of a second as an unsigned word32 4.294 967 296E9
577 WebRtc_UWord32 cameraDelayFixFrac = (WebRtc_UWord32)(-_cameraDelayMS)* 4294967; // note camera delay can't be larger than +/-1000ms
578 if(NTPfrac > 0xffffffff - cameraDelayFixFrac)
579 {
580 // we need to add the sec and add that sec to the frac
581 BackTimedNTPsec = NTPsec + 1;
582 BackTimedNTPfrac = cameraDelayFixFrac + NTPfrac; // this will wrap but that is ok
583 } else
584 {
585 // no problem just add the fraction part
586 BackTimedNTPsec = NTPsec;
587 BackTimedNTPfrac = NTPfrac + cameraDelayFixFrac;
588 }
589 }
590 _lastSendReport[0] = (BackTimedNTPsec <<16) + (BackTimedNTPfrac >> 16);
591
592 // RTP timestamp
593 // This should have a ramdom start value added
594 // RTP is counted from NTP not the acctual RTP
595 // This reflects the perfect RTP time
596 // we solve this by initiating RTP to our NTP :)
597
598 WebRtc_UWord32 freqHz = 90000; // For video
599 if(_audio)
600 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000601 freqHz = _rtpRtcp.CurrentSendFrequencyHz();
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000602 RTPtime = ModuleRTPUtility::GetCurrentRTP(&_clock, freqHz);
niklase@google.com470e71d2011-07-07 08:21:25 +0000603 }
604 else // video
605 {
606 // used to be (WebRtc_UWord32)(((float)BackTimedNTPfrac/(float)FRAC)* 90000)
607 WebRtc_UWord32 tmp = 9*(BackTimedNTPfrac/429496);
608 RTPtime = BackTimedNTPsec*freqHz + tmp;
609 }
610
611
612
613
614 // Add sender data
615 // Save for our length field
616 pos++;
617 pos++;
618
619 // Add our own SSRC
620 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
621 pos += 4;
622 // NTP
623 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, BackTimedNTPsec);
624 pos += 4;
625 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, BackTimedNTPfrac);
626 pos += 4;
627 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
628 pos += 4;
629
630 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000631 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000632 pos += 4;
633
634 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000635 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000636 pos += 4;
637
638 WebRtc_UWord8 numberOfReportBlocks = 0;
639 WebRtc_Word32 retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
640 if(retVal < 0)
641 {
642 //
643 return retVal ;
644 }
645 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
646
647 WebRtc_UWord16 len = WebRtc_UWord16((pos/4) -1);
648 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
649 return 0;
650}
651
652
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000653WebRtc_Word32 RTCPSender::BuildSDEC(WebRtc_UWord8* rtcpbuffer,
654 WebRtc_UWord32& pos) {
655 size_t lengthCname = strlen(_CNAME);
656 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000657
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000658 // sanity
659 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
660 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
661 "%s invalid argument", __FUNCTION__);
662 return -2;
663 }
664 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000665
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000666 // We always need to add SDES CNAME
667 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(0x80 + 1 + _csrcCNAMEs.size());
668 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000669
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000670 // handle SDES length later on
671 WebRtc_UWord32 SDESLengthPos = pos;
672 pos++;
673 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000674
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000675 // Add our own SSRC
676 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
677 pos += 4;
678
679 // CNAME = 1
680 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(1);
681
682 //
683 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(lengthCname);
684
685 WebRtc_UWord16 SDESLength = 10;
686
687 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
688 pos += lengthCname;
689 SDESLength += (WebRtc_UWord16)lengthCname;
690
691 WebRtc_UWord16 padding = 0;
692 // We must have a zero field even if we have an even multiple of 4 bytes
693 if ((pos % 4) == 0) {
694 padding++;
695 rtcpbuffer[pos++]=0;
696 }
697 while ((pos % 4) != 0) {
698 padding++;
699 rtcpbuffer[pos++]=0;
700 }
701 SDESLength += padding;
702
703 std::map<WebRtc_UWord32, RTCPUtility::RTCPCnameInformation*>::iterator it =
704 _csrcCNAMEs.begin();
705
706 for(; it != _csrcCNAMEs.end(); it++) {
707 RTCPCnameInformation* cname = it->second;
708 WebRtc_UWord32 SSRC = it->first;
709
710 // Add SSRC
711 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000712 pos += 4;
713
714 // CNAME = 1
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000715 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000716
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000717 size_t length = strlen(cname->name);
718 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000719
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000720 rtcpbuffer[pos++]= static_cast<WebRtc_UWord8>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000721 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000722
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000723 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000724
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000725 pos += length;
726 SDESLength += length;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000727 WebRtc_UWord16 padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000728
729 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000730 if((pos % 4) == 0){
731 padding++;
732 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000733 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000734 while((pos % 4) != 0){
735 padding++;
736 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000737 }
738 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000739 }
740 // in 32-bit words minus one and we don't count the header
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000741 WebRtc_UWord16 buffer_length = (SDESLength / 4) - 1;
742 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
743 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000744 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000745}
746
747WebRtc_Word32
748RTCPSender::BuildRR(WebRtc_UWord8* rtcpbuffer,
749 WebRtc_UWord32& pos,
750 const WebRtc_UWord32 NTPsec,
751 const WebRtc_UWord32 NTPfrac,
752 const RTCPReportBlock* received)
753{
754 // sanity one block
755 if(pos + 32 >= IP_PACKET_SIZE)
756 {
757 return -2;
758 }
759 WebRtc_UWord32 posNumberOfReportBlocks = pos;
760
761 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
762 rtcpbuffer[pos++]=(WebRtc_UWord8)201;
763
764 // Save for our length field
765 pos++;
766 pos++;
767
768 // Add our own SSRC
769 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
770 pos += 4;
771
772 WebRtc_UWord8 numberOfReportBlocks = 0;
773 WebRtc_Word32 retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
774 if(retVal < 0)
775 {
776 return retVal;
777 }
778 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
779
780 WebRtc_UWord16 len = WebRtc_UWord16((pos)/4 -1);
781 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
782 return 0;
783}
784
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000785// From RFC 5450: Transmission Time Offsets in RTP Streams.
786// 0 1 2 3
787// 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
788// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
789// hdr |V=2|P| RC | PT=IJ=195 | length |
790// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
791// | inter-arrival jitter |
792// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
793// . .
794// . .
795// . .
796// | inter-arrival jitter |
797// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
798//
799// If present, this RTCP packet must be placed after a receiver report
800// (inside a compound RTCP packet), and MUST have the same value for RC
801// (reception report count) as the receiver report.
802
803WebRtc_Word32
804RTCPSender::BuildExtendedJitterReport(
805 WebRtc_UWord8* rtcpbuffer,
806 WebRtc_UWord32& pos,
807 const WebRtc_UWord32 jitterTransmissionTimeOffset)
808{
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000809 if (_reportBlocks.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000810 {
811 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
812 return 0;
813 }
814
815 // sanity
816 if(pos + 8 >= IP_PACKET_SIZE)
817 {
818 return -2;
819 }
820 // add picture loss indicator
821 WebRtc_UWord8 RC = 1;
822 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + RC;
823 rtcpbuffer[pos++]=(WebRtc_UWord8)195;
824
825 // Used fixed length of 2
826 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
827 rtcpbuffer[pos++]=(WebRtc_UWord8)(1);
828
829 // Add inter-arrival jitter
830 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
831 jitterTransmissionTimeOffset);
832 pos += 4;
833 return 0;
834}
835
niklase@google.com470e71d2011-07-07 08:21:25 +0000836WebRtc_Word32
837RTCPSender::BuildPLI(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
838{
839 // sanity
840 if(pos + 12 >= IP_PACKET_SIZE)
841 {
842 return -2;
843 }
844 // add picture loss indicator
845 WebRtc_UWord8 FMT = 1;
846 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
847 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
848
849 //Used fixed length of 2
850 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
851 rtcpbuffer[pos++]=(WebRtc_UWord8)(2);
852
853 // Add our own SSRC
854 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
855 pos += 4;
856
857 // Add the remote SSRC
858 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
859 pos += 4;
860 return 0;
861}
862
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000863WebRtc_Word32 RTCPSender::BuildFIR(WebRtc_UWord8* rtcpbuffer,
864 WebRtc_UWord32& pos,
865 bool repeat) {
866 // sanity
867 if(pos + 20 >= IP_PACKET_SIZE) {
868 return -2;
869 }
870 if (!repeat) {
871 _sequenceNumberFIR++; // do not increase if repetition
872 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000873
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000874 // add full intra request indicator
875 WebRtc_UWord8 FMT = 4;
876 rtcpbuffer[pos++] = (WebRtc_UWord8)0x80 + FMT;
877 rtcpbuffer[pos++] = (WebRtc_UWord8)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000878
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000879 //Length of 4
880 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
881 rtcpbuffer[pos++] = (WebRtc_UWord8)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000882
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000883 // Add our own SSRC
884 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
885 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000886
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000887 // RFC 5104 4.3.1.2. Semantics
888 // SSRC of media source
889 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
890 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
891 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
892 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000893
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000894 // Additional Feedback Control Information (FCI)
895 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
896 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000897
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000898 rtcpbuffer[pos++] = (WebRtc_UWord8)(_sequenceNumberFIR);
899 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
900 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
901 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
902 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000903}
904
905/*
906 0 1 2 3
907 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
908 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
909 | First | Number | PictureID |
910 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
911*/
912WebRtc_Word32
913RTCPSender::BuildSLI(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos, const WebRtc_UWord8 pictureID)
914{
915 // sanity
916 if(pos + 16 >= IP_PACKET_SIZE)
917 {
918 return -2;
919 }
920 // add slice loss indicator
921 WebRtc_UWord8 FMT = 2;
922 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
923 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
924
925 //Used fixed length of 3
926 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
927 rtcpbuffer[pos++]=(WebRtc_UWord8)(3);
928
929 // Add our own SSRC
930 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
931 pos += 4;
932
933 // Add the remote SSRC
934 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
935 pos += 4;
936
937 // Add first, number & picture ID 6 bits
938 // first = 0, 13 - bits
939 // number = 0x1fff, 13 - bits only ones for now
940 WebRtc_UWord32 sliField = (0x1fff << 6)+ (0x3f & pictureID);
941 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
942 pos += 4;
943 return 0;
944}
945
946/*
947 0 1 2 3
948 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
949 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
950 | PB |0| Payload Type| Native RPSI bit string |
951 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
952 | defined per codec ... | Padding (0) |
953 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
954*/
955/*
956* Note: not generic made for VP8
957*/
958WebRtc_Word32
959RTCPSender::BuildRPSI(WebRtc_UWord8* rtcpbuffer,
960 WebRtc_UWord32& pos,
961 const WebRtc_UWord64 pictureID,
962 const WebRtc_UWord8 payloadType)
963{
964 // sanity
965 if(pos + 24 >= IP_PACKET_SIZE)
966 {
967 return -2;
968 }
969 // add Reference Picture Selection Indication
970 WebRtc_UWord8 FMT = 3;
971 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
972 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
973
974 // calc length
975 WebRtc_UWord32 bitsRequired = 7;
976 WebRtc_UWord8 bytesRequired = 1;
977 while((pictureID>>bitsRequired) > 0)
978 {
979 bitsRequired += 7;
980 bytesRequired++;
981 }
982
983 WebRtc_UWord8 size = 3;
984 if(bytesRequired > 6)
985 {
986 size = 5;
987 } else if(bytesRequired > 2)
988 {
989 size = 4;
990 }
991 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
992 rtcpbuffer[pos++]=size;
993
994 // Add our own SSRC
995 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
996 pos += 4;
997
998 // Add the remote SSRC
999 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1000 pos += 4;
1001
1002 // calc padding length
1003 WebRtc_UWord8 paddingBytes = 4-((2+bytesRequired)%4);
1004 if(paddingBytes == 4)
1005 {
1006 paddingBytes = 0;
1007 }
1008 // add padding length in bits
1009 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1010 pos++;
1011
1012 // add payload type
1013 rtcpbuffer[pos] = payloadType;
1014 pos++;
1015
1016 // add picture ID
1017 for(int i = bytesRequired-1; i > 0; i--)
1018 {
1019 rtcpbuffer[pos] = 0x80 | WebRtc_UWord8(pictureID >> (i*7));
1020 pos++;
1021 }
1022 // add last byte of picture ID
1023 rtcpbuffer[pos] = WebRtc_UWord8(pictureID & 0x7f);
1024 pos++;
1025
1026 // add padding
1027 for(int j = 0; j <paddingBytes; j++)
1028 {
1029 rtcpbuffer[pos] = 0;
1030 pos++;
1031 }
1032 return 0;
1033}
1034
1035WebRtc_Word32
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001036RTCPSender::BuildREMB(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1037{
1038 // sanity
1039 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1040 {
1041 return -2;
1042 }
1043 // add application layer feedback
1044 WebRtc_UWord8 FMT = 15;
1045 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1046 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
1047
1048 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1049 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1050
1051 // Add our own SSRC
1052 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1053 pos += 4;
1054
1055 // Remote SSRC must be 0
1056 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1057 pos += 4;
1058
1059 rtcpbuffer[pos++]='R';
1060 rtcpbuffer[pos++]='E';
1061 rtcpbuffer[pos++]='M';
1062 rtcpbuffer[pos++]='B';
1063
1064 rtcpbuffer[pos++] = _lengthRembSSRC;
1065 // 6 bit Exp
1066 // 18 bit mantissa
1067 WebRtc_UWord8 brExp = 0;
1068 for(WebRtc_UWord32 i=0; i<64; i++)
1069 {
1070 if(_rembBitrate <= ((WebRtc_UWord32)262143 << i))
1071 {
1072 brExp = i;
1073 break;
1074 }
1075 }
1076 const WebRtc_UWord32 brMantissa = (_rembBitrate >> brExp);
1077 rtcpbuffer[pos++]=(WebRtc_UWord8)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1078 rtcpbuffer[pos++]=(WebRtc_UWord8)(brMantissa >> 8);
1079 rtcpbuffer[pos++]=(WebRtc_UWord8)(brMantissa);
1080
1081 for (int i = 0; i < _lengthRembSSRC; i++)
1082 {
1083 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1084 pos += 4;
1085 }
1086 return 0;
1087}
1088
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001089void
1090RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001091{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001092 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001093 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001094}
1095
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001096WebRtc_Word32
1097RTCPSender::BuildTMMBR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001098{
1099 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1100 // If the sender is an owner of the TMMBN -> send TMMBR
1101 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1102
niklase@google.com470e71d2011-07-07 08:21:25 +00001103 // get current bounding set from RTCP receiver
1104 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001105 // store in candidateSet, allocates one extra slot
1106 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001107
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001108 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1109 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1110 // since RTCPreceiver is not doing the reverse we should be fine
1111 WebRtc_Word32 lengthOfBoundingSet
1112 = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001113
1114 if(lengthOfBoundingSet > 0)
1115 {
1116 for (WebRtc_Word32 i = 0; i < lengthOfBoundingSet; i++)
1117 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001118 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1119 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001120 {
1121 // do not send the same tuple
1122 return 0;
1123 }
1124 }
1125 if(!tmmbrOwner)
1126 {
1127 // use received bounding set as candidate set
1128 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001129 candidateSet->SetEntry(lengthOfBoundingSet,
1130 _tmmbr_Send,
1131 _packetOH_Send,
1132 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001133 int numCandidates = lengthOfBoundingSet+ 1;
1134
1135 // find bounding set
1136 TMMBRSet* boundingSet = NULL;
1137 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1138 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1139 {
1140 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1141 }
1142 if(!tmmbrOwner)
1143 {
1144 // did not enter bounding set, no meaning to send this request
1145 return 0;
1146 }
1147 }
1148 }
1149
1150 if(_tmmbr_Send)
1151 {
1152 // sanity
1153 if(pos + 20 >= IP_PACKET_SIZE)
1154 {
1155 return -2;
1156 }
1157 // add TMMBR indicator
1158 WebRtc_UWord8 FMT = 3;
1159 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1160 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1161
1162 //Length of 4
1163 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1164 rtcpbuffer[pos++]=(WebRtc_UWord8)(4);
1165
1166 // Add our own SSRC
1167 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1168 pos += 4;
1169
1170 // RFC 5104 4.2.1.2. Semantics
1171
1172 // SSRC of media source
1173 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1174 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1175 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1176 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1177
1178 // Additional Feedback Control Information (FCI)
1179 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1180 pos += 4;
1181
1182 WebRtc_UWord32 bitRate = _tmmbr_Send*1000;
1183 WebRtc_UWord32 mmbrExp = 0;
1184 for(WebRtc_UWord32 i=0;i<64;i++)
1185 {
1186 if(bitRate <= ((WebRtc_UWord32)131071 << i))
1187 {
1188 mmbrExp = i;
1189 break;
1190 }
1191 }
1192 WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp);
1193
1194 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1195 rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);
1196 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1197 rtcpbuffer[pos++]=(WebRtc_UWord8)(_packetOH_Send);
1198 }
1199 return 0;
1200}
1201
1202WebRtc_Word32
1203RTCPSender::BuildTMMBN(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1204{
1205 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1206 if(boundingSet == NULL)
1207 {
1208 return -1;
1209 }
1210 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001211 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001212 {
1213 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1214 return -2;
1215 }
1216 WebRtc_UWord8 FMT = 4;
1217 // add TMMBN indicator
1218 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1219 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1220
1221 //Add length later
1222 int posLength = pos;
1223 pos++;
1224 pos++;
1225
1226 // Add our own SSRC
1227 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1228 pos += 4;
1229
1230 // RFC 5104 4.2.2.2. Semantics
1231
1232 // SSRC of media source
1233 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1234 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1235 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1236 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1237
1238 // Additional Feedback Control Information (FCI)
1239 int numBoundingSet = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001240 for(WebRtc_UWord32 n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001241 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001242 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001243 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001244 WebRtc_UWord32 tmmbrSSRC = boundingSet->Ssrc(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001245 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1246 pos += 4;
1247
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001248 WebRtc_UWord32 bitRate = boundingSet->Tmmbr(n) * 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001249 WebRtc_UWord32 mmbrExp = 0;
1250 for(int i=0; i<64; i++)
1251 {
1252 if(bitRate <= ((WebRtc_UWord32)131071 << i))
1253 {
1254 mmbrExp = i;
1255 break;
1256 }
1257 }
1258 WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp);
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001259 WebRtc_UWord32 measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001260
1261 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1262 rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);
1263 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1264 rtcpbuffer[pos++]=(WebRtc_UWord8)(measuredOH);
1265 numBoundingSet++;
1266 }
1267 }
1268 WebRtc_UWord16 length= (WebRtc_UWord16)(2+2*numBoundingSet);
1269 rtcpbuffer[posLength++]=(WebRtc_UWord8)(length>>8);
1270 rtcpbuffer[posLength]=(WebRtc_UWord8)(length);
1271 return 0;
1272}
1273
1274WebRtc_Word32
1275RTCPSender::BuildAPP(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1276{
1277 // sanity
1278 if(_appData == NULL)
1279 {
1280 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1281 return -1;
1282 }
1283 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1284 {
1285 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1286 return -2;
1287 }
1288 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + _appSubType;
1289
1290 // Add APP ID
1291 rtcpbuffer[pos++]=(WebRtc_UWord8)204;
1292
1293 WebRtc_UWord16 length = (_appLength>>2) + 2; // include SSRC and name
1294 rtcpbuffer[pos++]=(WebRtc_UWord8)(length>>8);
1295 rtcpbuffer[pos++]=(WebRtc_UWord8)(length);
1296
1297 // Add our own SSRC
1298 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1299 pos += 4;
1300
1301 // Add our application name
1302 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1303 pos += 4;
1304
1305 // Add the data
1306 memcpy(rtcpbuffer +pos, _appData,_appLength);
1307 pos += _appLength;
1308 return 0;
1309}
1310
1311WebRtc_Word32
1312RTCPSender::BuildNACK(WebRtc_UWord8* rtcpbuffer,
1313 WebRtc_UWord32& pos,
1314 const WebRtc_Word32 nackSize,
1315 const WebRtc_UWord16* nackList)
1316{
1317 // sanity
1318 if(pos + 16 >= IP_PACKET_SIZE)
1319 {
1320 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1321 return -2;
1322 }
1323
1324 // int size, WebRtc_UWord16* nackList
1325 // add nack list
1326 WebRtc_UWord8 FMT = 1;
1327 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1328 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1329
1330 rtcpbuffer[pos++]=(WebRtc_UWord8) 0;
1331 int nackSizePos = pos;
1332 rtcpbuffer[pos++]=(WebRtc_UWord8)(3); //setting it to one kNACK signal as default
1333
1334 // Add our own SSRC
1335 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1336 pos += 4;
1337
1338 // Add the remote SSRC
1339 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1340 pos += 4;
1341
1342 // add the list
1343 int i = 0;
1344 int numOfNackFields = 0;
1345 while(nackSize > i && numOfNackFields < 253)
1346 {
1347 WebRtc_UWord16 nack = nackList[i];
1348 // put dow our sequence number
1349 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, nack);
1350 pos += 2;
1351
1352 i++;
1353 numOfNackFields++;
1354 if(nackSize > i)
1355 {
1356 bool moreThan16Away = (WebRtc_UWord16(nack+16) < nackList[i])?true: false;
1357 if(!moreThan16Away)
1358 {
1359 // check for a wrap
1360 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1361 {
1362 // wrap
1363 moreThan16Away = true;
1364 }
1365 }
1366 if(moreThan16Away)
1367 {
1368 // next is more than 16 away
1369 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1370 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1371 } else
1372 {
1373 // build our bitmask
1374 WebRtc_UWord16 bitmask = 0;
1375
1376 bool within16Away = (WebRtc_UWord16(nack+16) > nackList[i])?true: false;
1377 if(within16Away)
1378 {
1379 // check for a wrap
1380 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1381 {
1382 // wrap
1383 within16Away = false;
1384 }
1385 }
1386
1387 while( nackSize > i && within16Away)
1388 {
1389 WebRtc_Word16 shift = (nackList[i]-nack)-1;
1390 assert(!(shift > 15) && !(shift < 0));
1391
1392 bitmask += (1<< shift);
1393 i++;
1394 if(nackSize > i)
1395 {
1396 within16Away = (WebRtc_UWord16(nack+16) > nackList[i])?true: false;
1397 if(within16Away)
1398 {
1399 // check for a wrap
1400 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1401 {
1402 // wrap
1403 within16Away = false;
1404 }
1405 }
1406 }
1407 }
1408 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, bitmask);
1409 pos += 2;
1410 }
1411 // sanity do we have room from one more 4 byte block?
1412 if(pos + 4 >= IP_PACKET_SIZE)
1413 {
1414 return -2;
1415 }
1416 } else
1417 {
1418 // no more in the list
1419 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1420 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1421 }
1422 }
1423 rtcpbuffer[nackSizePos]=(WebRtc_UWord8)(2+numOfNackFields);
1424 return 0;
1425}
1426
1427WebRtc_Word32
1428RTCPSender::BuildBYE(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1429{
1430 // sanity
1431 if(pos + 8 >= IP_PACKET_SIZE)
1432 {
1433 return -2;
1434 }
1435 if(_includeCSRCs)
1436 {
1437 // Add a bye packet
1438 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1439 rtcpbuffer[pos++]=(WebRtc_UWord8)203;
1440
1441 // length
1442 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1443 rtcpbuffer[pos++]=(WebRtc_UWord8)(1 + _CSRCs);
1444
1445 // Add our own SSRC
1446 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1447 pos += 4;
1448
1449 // add CSRCs
1450 for(int i = 0; i < _CSRCs; i++)
1451 {
1452 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1453 pos += 4;
1454 }
1455 } else
1456 {
1457 // Add a bye packet
1458 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1; // number of SSRC+CSRCs
1459 rtcpbuffer[pos++]=(WebRtc_UWord8)203;
1460
1461 // length
1462 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1463 rtcpbuffer[pos++]=(WebRtc_UWord8)1;
1464
1465 // Add our own SSRC
1466 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1467 pos += 4;
1468 }
1469 return 0;
1470}
1471
1472WebRtc_Word32
1473RTCPSender::BuildVoIPMetric(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1474{
1475 // sanity
1476 if(pos + 44 >= IP_PACKET_SIZE)
1477 {
1478 return -2;
1479 }
1480
1481 // Add XR header
1482 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
1483 rtcpbuffer[pos++]=(WebRtc_UWord8)207;
1484
1485 WebRtc_UWord32 XRLengthPos = pos;
1486
1487 // handle length later on
1488 pos++;
1489 pos++;
1490
1491 // Add our own SSRC
1492 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1493 pos += 4;
1494
1495 // Add a VoIP metrics block
1496 rtcpbuffer[pos++]=7;
1497 rtcpbuffer[pos++]=0;
1498 rtcpbuffer[pos++]=0;
1499 rtcpbuffer[pos++]=8;
1500
1501 // Add the remote SSRC
1502 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1503 pos += 4;
1504
1505 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1506 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1507 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1508 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1509
1510 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.burstDuration >> 8);
1511 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.burstDuration);
1512 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.gapDuration >> 8);
1513 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.gapDuration);
1514
1515 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.roundTripDelay >> 8);
1516 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.roundTripDelay);
1517 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.endSystemDelay >> 8);
1518 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.endSystemDelay);
1519
1520 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1521 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1522 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1523 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1524
1525 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1526 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1527 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1528 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1529
1530 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1531 rtcpbuffer[pos++] = 0; // reserved
1532 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBnominal >> 8);
1533 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBnominal);
1534
1535 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBmax >> 8);
1536 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBmax);
1537 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBabsMax >> 8);
1538 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBabsMax);
1539
1540 rtcpbuffer[XRLengthPos]=(WebRtc_UWord8)(0);
1541 rtcpbuffer[XRLengthPos+1]=(WebRtc_UWord8)(10);
1542 return 0;
1543}
1544
1545WebRtc_Word32
1546RTCPSender::SendRTCP(const WebRtc_UWord32 packetTypeFlags,
1547 const WebRtc_Word32 nackSize, // NACK
1548 const WebRtc_UWord16* nackList, // NACK
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001549 const bool repeat, // FIR
niklase@google.com470e71d2011-07-07 08:21:25 +00001550 const WebRtc_UWord64 pictureID) // SLI & RPSI
1551{
1552 WebRtc_UWord32 rtcpPacketTypeFlags = packetTypeFlags;
1553 WebRtc_UWord32 pos = 0;
1554 WebRtc_UWord8 rtcpbuffer[IP_PACKET_SIZE];
1555
niklase@google.com470e71d2011-07-07 08:21:25 +00001556 do // only to be able to use break :) (and the critsect must be inside its own scope)
1557 {
1558 // collect the received information
1559 RTCPReportBlock received;
1560 bool hasReceived = false;
1561 WebRtc_UWord32 NTPsec = 0;
1562 WebRtc_UWord32 NTPfrac = 0;
xians@webrtc.org8738d272011-11-25 13:43:53 +00001563 bool rtcpCompound = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001564 WebRtc_UWord32 jitterTransmissionOffset = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001565
xians@webrtc.org8738d272011-11-25 13:43:53 +00001566 {
1567 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1568 if(_method == kRtcpOff)
1569 {
1570 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1571 "%s invalid state", __FUNCTION__);
1572 return -1;
1573 }
1574 rtcpCompound = (_method == kRtcpCompound) ? true : false;
1575 }
1576
1577 if (rtcpCompound ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001578 rtcpPacketTypeFlags & kRtcpReport ||
1579 rtcpPacketTypeFlags & kRtcpSr ||
1580 rtcpPacketTypeFlags & kRtcpRr)
1581 {
1582 // get statistics from our RTPreceiver outside critsect
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001583 if(_rtpRtcp.ReportBlockStatistics(&received.fractionLost,
1584 &received.cumulativeLost,
1585 &received.extendedHighSeqNum,
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001586 &received.jitter,
1587 &jitterTransmissionOffset) == 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001588 {
1589 hasReceived = true;
1590
1591 WebRtc_UWord32 lastReceivedRRNTPsecs = 0;
1592 WebRtc_UWord32 lastReceivedRRNTPfrac = 0;
1593 WebRtc_UWord32 remoteSR = 0;
1594
1595 // ok even if we have not received a SR, we will send 0 in that case
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001596 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1597 lastReceivedRRNTPfrac,
1598 remoteSR);
niklase@google.com470e71d2011-07-07 08:21:25 +00001599
1600 // get our NTP as late as possible to avoid a race
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001601 _clock.CurrentNTP(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001602
1603 // Delay since last received report
1604 WebRtc_UWord32 delaySinceLastReceivedSR = 0;
1605 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
1606 {
1607 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1608 WebRtc_UWord32 now=NTPsec&0x0000FFFF;
1609 now <<=16;
1610 now += (NTPfrac&0xffff0000)>>16;
1611
1612 WebRtc_UWord32 receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
1613 receiveTime <<=16;
1614 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1615
1616 delaySinceLastReceivedSR = now-receiveTime;
1617 }
1618 received.delaySinceLastSR = delaySinceLastReceivedSR;
1619 received.lastSR = remoteSR;
1620 } else
1621 {
1622 // we need to send our NTP even if we dont have received any reports
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001623 _clock.CurrentNTP(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001624 }
1625 }
1626
1627 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1628
1629 if(_TMMBR ) // attach TMMBR to send and receive reports
1630 {
1631 rtcpPacketTypeFlags |= kRtcpTmmbr;
1632 }
1633 if(_appSend)
1634 {
1635 rtcpPacketTypeFlags |= kRtcpApp;
1636 _appSend = false;
1637 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001638 if(_REMB && _sendREMB)
1639 {
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +00001640 // Always attach REMB to SR if that is configured. Note that REMB is
1641 // only sent on one of the RTP modules in the REMB group.
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001642 rtcpPacketTypeFlags |= kRtcpRemb;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001643 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001644 if(_xrSendVoIPMetric)
1645 {
1646 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1647 _xrSendVoIPMetric = false;
1648 }
1649 if(_sendTMMBN) // set when having received a TMMBR
1650 {
1651 rtcpPacketTypeFlags |= kRtcpTmmbn;
1652 _sendTMMBN = false;
1653 }
1654
1655 if(_method == kRtcpCompound)
1656 {
1657 if(_sending)
1658 {
1659 rtcpPacketTypeFlags |= kRtcpSr;
1660 } else
1661 {
1662 rtcpPacketTypeFlags |= kRtcpRr;
1663 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001664 if (_IJ && hasReceived)
1665 {
1666 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1667 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001668 } else if(_method == kRtcpNonCompound)
1669 {
1670 if(rtcpPacketTypeFlags & kRtcpReport)
1671 {
1672 if(_sending)
1673 {
1674 rtcpPacketTypeFlags |= kRtcpSr;
1675 } else
1676 {
1677 rtcpPacketTypeFlags |= kRtcpRr;
1678 }
1679 }
1680 }
1681 if( rtcpPacketTypeFlags & kRtcpRr ||
1682 rtcpPacketTypeFlags & kRtcpSr)
1683 {
1684 // generate next time to send a RTCP report
1685 // seeded from RTP constructor
1686 WebRtc_Word32 random = rand() % 1000;
1687 WebRtc_Word32 timeToNext = RTCP_INTERVAL_AUDIO_MS;
1688
1689 if(_audio)
1690 {
1691 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
1692 }else
1693 {
1694 WebRtc_UWord32 minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1695 if(_sending)
1696 {
1697 // calc bw for video 360/sendBW in kbit/s
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001698 WebRtc_UWord32 sendBitrateKbit = 0;
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001699 WebRtc_UWord32 videoRate = 0;
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001700 WebRtc_UWord32 fecRate = 0;
1701 WebRtc_UWord32 nackRate = 0;
1702 _rtpRtcp.BitrateSent(&sendBitrateKbit,
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001703 &videoRate,
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001704 &fecRate,
1705 &nackRate);
1706 sendBitrateKbit /= 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001707 if(sendBitrateKbit != 0)
1708 {
1709 minIntervalMs = 360000/sendBitrateKbit;
1710 }
1711 }
1712 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1713 {
1714 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1715 }
1716 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1717 }
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001718 _nextTimeToSendRTCP = _clock.GetTimeInMS() + timeToNext;
niklase@google.com470e71d2011-07-07 08:21:25 +00001719 }
1720
1721 // if the data does not fitt in the packet we fill it as much as possible
1722 WebRtc_Word32 buildVal = 0;
1723
1724 if(rtcpPacketTypeFlags & kRtcpSr)
1725 {
1726 if(hasReceived)
1727 {
1728 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
1729 } else
1730 {
1731 buildVal = BuildSR(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 buildVal = BuildSDEC(rtcpbuffer, pos);
1742 if(buildVal == -1)
1743 {
1744 return -1; // error
1745
1746 }else if(buildVal == -2)
1747 {
1748 break; // out of buffer
1749 }
1750
1751 }else if(rtcpPacketTypeFlags & kRtcpRr)
1752 {
1753 if(hasReceived)
1754 {
1755 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
1756 }else
1757 {
1758 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
1759 }
1760 if(buildVal == -1)
1761 {
1762 return -1; // error
1763
1764 }else if(buildVal == -2)
1765 {
1766 break; // out of buffer
1767 }
1768 // only of set
1769 if(_CNAME[0] != 0)
1770 {
1771 buildVal = BuildSDEC(rtcpbuffer, pos);
1772 if(buildVal == -1)
1773 {
1774 return -1; // error
1775 }
1776 }
1777 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001778 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1779 {
1780 // If present, this RTCP packet must be placed after a
1781 // receiver report.
1782 buildVal = BuildExtendedJitterReport(rtcpbuffer,
1783 pos,
1784 jitterTransmissionOffset);
1785 if(buildVal == -1)
1786 {
1787 return -1; // error
1788 }
1789 else if(buildVal == -2)
1790 {
1791 break; // out of buffer
1792 }
1793 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001794 if(rtcpPacketTypeFlags & kRtcpPli)
1795 {
1796 buildVal = BuildPLI(rtcpbuffer, pos);
1797 if(buildVal == -1)
1798 {
1799 return -1; // error
1800
1801 }else if(buildVal == -2)
1802 {
1803 break; // out of buffer
1804 }
1805 }
1806 if(rtcpPacketTypeFlags & kRtcpFir)
1807 {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001808 buildVal = BuildFIR(rtcpbuffer, pos, repeat);
niklase@google.com470e71d2011-07-07 08:21:25 +00001809 if(buildVal == -1)
1810 {
1811 return -1; // error
1812
1813 }else if(buildVal == -2)
1814 {
1815 break; // out of buffer
1816 }
1817 }
1818 if(rtcpPacketTypeFlags & kRtcpSli)
1819 {
1820 buildVal = BuildSLI(rtcpbuffer, pos, (WebRtc_UWord8)pictureID);
1821 if(buildVal == -1)
1822 {
1823 return -1; // error
1824
1825 }else if(buildVal == -2)
1826 {
1827 break; // out of buffer
1828 }
1829 }
1830 if(rtcpPacketTypeFlags & kRtcpRpsi)
1831 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001832 const WebRtc_Word8 payloadType = _rtpRtcp.SendPayloadType();
niklase@google.com470e71d2011-07-07 08:21:25 +00001833 if(payloadType == -1)
1834 {
1835 return -1;
1836 }
1837 buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (WebRtc_UWord8)payloadType);
1838 if(buildVal == -1)
1839 {
1840 return -1; // error
1841
1842 }else if(buildVal == -2)
1843 {
1844 break; // out of buffer
1845 }
1846 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001847 if(rtcpPacketTypeFlags & kRtcpRemb)
1848 {
1849 buildVal = BuildREMB(rtcpbuffer, pos);
1850 if(buildVal == -1)
1851 {
1852 return -1; // error
1853
1854 }else if(buildVal == -2)
1855 {
1856 break; // out of buffer
1857 }
1858 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001859 if(rtcpPacketTypeFlags & kRtcpBye)
1860 {
1861 buildVal = BuildBYE(rtcpbuffer, pos);
1862 if(buildVal == -1)
1863 {
1864 return -1; // error
1865
1866 }else if(buildVal == -2)
1867 {
1868 break; // out of buffer
1869 }
1870 }
1871 if(rtcpPacketTypeFlags & kRtcpApp)
1872 {
1873 buildVal = BuildAPP(rtcpbuffer, pos);
1874 if(buildVal == -1)
1875 {
1876 return -1; // error
1877
1878 }else if(buildVal == -2)
1879 {
1880 break; // out of buffer
1881 }
1882 }
1883 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1884 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001885 buildVal = BuildTMMBR(rtcpbuffer, pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001886 if(buildVal == -1)
1887 {
1888 return -1; // error
1889
1890 }else if(buildVal == -2)
1891 {
1892 break; // out of buffer
1893 }
1894 }
1895 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1896 {
1897 buildVal = BuildTMMBN(rtcpbuffer, pos);
1898 if(buildVal == -1)
1899 {
1900 return -1; // error
1901
1902 }else if(buildVal == -2)
1903 {
1904 break; // out of buffer
1905 }
1906 }
1907 if(rtcpPacketTypeFlags & kRtcpNack)
1908 {
1909 buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList);
1910 if(buildVal == -1)
1911 {
1912 return -1; // error
1913
1914 }else if(buildVal == -2)
1915 {
1916 break; // out of buffer
1917 }
1918 }
1919 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1920 {
1921 buildVal = BuildVoIPMetric(rtcpbuffer, pos);
1922 if(buildVal == -1)
1923 {
1924 return -1; // error
1925
1926 }else if(buildVal == -2)
1927 {
1928 break; // out of buffer
1929 }
1930 }
1931 }while (false);
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001932 // Sanity don't send empty packets.
1933 if (pos == 0)
1934 {
1935 return -1;
1936 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001937 return SendToNetwork(rtcpbuffer, (WebRtc_UWord16)pos);
1938}
1939
1940WebRtc_Word32
1941RTCPSender::SendToNetwork(const WebRtc_UWord8* dataBuffer,
1942 const WebRtc_UWord16 length)
1943{
1944 CriticalSectionScoped lock(_criticalSectionTransport);
1945 if(_cbTransport)
1946 {
1947 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1948 {
1949 return 0;
1950 }
1951 }
1952 return -1;
1953}
1954
1955WebRtc_Word32
1956RTCPSender::SetCSRCStatus(const bool include)
1957{
1958 _includeCSRCs = include;
1959 return 0;
1960}
1961
1962WebRtc_Word32
1963RTCPSender::SetCSRCs(const WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize],
1964 const WebRtc_UWord8 arrLength)
1965{
1966 if(arrLength > kRtpCsrcSize)
1967 {
1968 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1969 assert(false);
1970 return -1;
1971 }
1972
1973 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1974
1975 for(int i = 0; i < arrLength;i++)
1976 {
1977 _CSRC[i] = arrOfCSRC[i];
1978 }
1979 _CSRCs = arrLength;
1980 return 0;
1981}
1982
1983WebRtc_Word32
1984RTCPSender::SetApplicationSpecificData(const WebRtc_UWord8 subType,
1985 const WebRtc_UWord32 name,
1986 const WebRtc_UWord8* data,
1987 const WebRtc_UWord16 length)
1988{
1989 if(length %4 != 0)
1990 {
1991 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1992 return -1;
1993 }
1994 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1995
1996 if(_appData)
1997 {
1998 delete [] _appData;
1999 }
2000
2001 _appSend = true;
2002 _appSubType = subType;
2003 _appName = name;
2004 _appData = new WebRtc_UWord8[length];
2005 _appLength = length;
2006 memcpy(_appData, data, length);
2007 return 0;
2008}
2009
2010WebRtc_Word32
2011RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2012{
2013 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2014 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2015
2016 _xrSendVoIPMetric = true;
2017 return 0;
2018}
2019
2020// called under critsect _criticalSectionRTCPSender
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002021WebRtc_Word32 RTCPSender::AddReportBlocks(WebRtc_UWord8* rtcpbuffer,
2022 WebRtc_UWord32& pos,
2023 WebRtc_UWord8& numberOfReportBlocks,
2024 const RTCPReportBlock* received,
2025 const WebRtc_UWord32 NTPsec,
2026 const WebRtc_UWord32 NTPfrac) {
2027 // sanity one block
2028 if(pos + 24 >= IP_PACKET_SIZE) {
2029 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2030 "%s invalid argument", __FUNCTION__);
2031 return -1;
2032 }
2033 numberOfReportBlocks = _reportBlocks.size();
2034 if (received) {
2035 // add our multiple RR to numberOfReportBlocks
2036 numberOfReportBlocks++;
2037 }
2038 if (received) {
2039 // answer to the one that sends to me
2040 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac);
2041
2042 // Remote SSRC
2043 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
2044 pos += 4;
2045
2046 // fraction lost
2047 rtcpbuffer[pos++]=received->fractionLost;
2048
2049 // cumulative loss
2050 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2051 received->cumulativeLost);
2052 pos += 3;
2053 // extended highest seq_no, contain the highest sequence number received
2054 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2055 received->extendedHighSeqNum);
2056 pos += 4;
2057
2058 //Jitter
2059 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
2060 pos += 4;
2061
2062 // Last SR timestamp, our NTP time when we received the last report
2063 // This is the value that we read from the send report packet not when we
2064 // received it...
2065 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
2066 pos += 4;
2067
2068 // Delay since last received report,time since we received the report
2069 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2070 received->delaySinceLastSR);
2071 pos += 4;
2072 }
2073 if ((pos + _reportBlocks.size() * 24) >= IP_PACKET_SIZE) {
2074 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2075 "%s invalid argument", __FUNCTION__);
2076 return -1;
2077 }
2078 std::map<WebRtc_UWord32, RTCPReportBlock*>::iterator it =
2079 _reportBlocks.begin();
2080
2081 for (; it != _reportBlocks.end(); it++) {
2082 // we can have multiple report block in a conference
2083 WebRtc_UWord32 remoteSSRC = it->first;
2084 RTCPReportBlock* reportBlock = it->second;
2085 if (reportBlock) {
2086 // Remote SSRC
2087 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
2088 pos += 4;
2089
2090 // fraction lost
2091 rtcpbuffer[pos++] = reportBlock->fractionLost;
2092
2093 // cumulative loss
2094 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2095 reportBlock->cumulativeLost);
2096 pos += 3;
2097
2098 // extended highest seq_no, contain the highest sequence number received
2099 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2100 reportBlock->extendedHighSeqNum);
2101 pos += 4;
2102
2103 //Jitter
2104 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2105 reportBlock->jitter);
2106 pos += 4;
2107
2108 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2109 reportBlock->lastSR);
2110 pos += 4;
2111
2112 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2113 reportBlock->delaySinceLastSR);
2114 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002115 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002116 }
2117 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00002118}
2119
2120// no callbacks allowed inside this function
2121WebRtc_Word32
2122RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
2123 const WebRtc_UWord32 maxBitrateKbit)
2124{
2125 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2126
2127 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2128 {
2129 _sendTMMBN = true;
2130 return 0;
2131 }
2132 return -1;
2133}
niklase@google.com470e71d2011-07-07 08:21:25 +00002134} // namespace webrtc