blob: 5d2e7dd725d4a38ce2047b03377a8e63b6841a6d [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
13#include <string.h> // memcpy
14#include <cassert> // assert
15#include <cstdlib> // rand
16
17#include "trace.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000018#include "common_types.h"
19#include "critical_section_wrapper.h"
20
pwestin@webrtc.org741da942011-09-20 13:52:04 +000021#include "rtp_rtcp_impl.h"
22
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),
mflodman@webrtc.org80d60422012-01-12 14:28:53 +000069 _bitrate_observer(NULL),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000070
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000071 _tmmbrHelp(),
niklase@google.com470e71d2011-07-07 08:21:25 +000072 _tmmbr_Send(0),
73 _packetOH_Send(0),
74 _remoteRateControl(),
75
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;
niklase@google.com470e71d2011-07-07 08:21:25 +0000127 _SSRC = 0;
128 _remoteSSRC = 0;
129 _cameraDelayMS = 0;
130 _sequenceNumberFIR = 0;
131 _tmmbr_Send = 0;
132 _packetOH_Send = 0;
133 _remoteRateControl.Reset();
134 _nextTimeToSendRTCP = 0;
135 _CSRCs = 0;
136 _appSend = false;
137 _appSubType = 0;
138
139 if(_appData)
140 {
141 delete [] _appData;
142 _appData = NULL;
143 }
144 _appLength = 0;
145
146 _xrSendVoIPMetric = false;
147
148 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
149 memset(_CNAME, 0, sizeof(_CNAME));
150 memset(_lastSendReport, 0, sizeof(_lastSendReport));
151 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
152 return 0;
153}
154
155void
156RTCPSender::ChangeUniqueId(const WebRtc_Word32 id)
157{
158 _id = id;
159}
160
161WebRtc_Word32
162RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
163{
164 CriticalSectionScoped lock(_criticalSectionTransport);
165 _cbTransport = outgoingTransport;
166 return 0;
167}
168
169RTCPMethod
170RTCPSender::Status() const
171{
172 CriticalSectionScoped lock(_criticalSectionRTCPSender);
173 return _method;
174}
175
176WebRtc_Word32
177RTCPSender::SetRTCPStatus(const RTCPMethod method)
178{
179 CriticalSectionScoped lock(_criticalSectionRTCPSender);
180 if(method != kRtcpOff)
181 {
182 if(_audio)
183 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000184 _nextTimeToSendRTCP = _clock.GetTimeInMS() + (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000185 } else
186 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000187 _nextTimeToSendRTCP = _clock.GetTimeInMS() + (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000188 }
189 }
190 _method = method;
191 return 0;
192}
193
194bool
195RTCPSender::Sending() const
196{
197 CriticalSectionScoped lock(_criticalSectionRTCPSender);
198 return _sending;
199}
200
201WebRtc_Word32
202RTCPSender::SetSendingStatus(const bool sending)
203{
204 bool sendRTCPBye = false;
205 {
206 CriticalSectionScoped lock(_criticalSectionRTCPSender);
207
208 if(_method != kRtcpOff)
209 {
210 if(sending == false && _sending == true)
211 {
212 // Trigger RTCP bye
213 sendRTCPBye = true;
214 }
215 }
216 _sending = sending;
217 }
218 if(sendRTCPBye)
219 {
220 return SendRTCP(kRtcpBye);
221 }
222 return 0;
223}
224
225bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000226RTCPSender::REMB() const
227{
228 CriticalSectionScoped lock(_criticalSectionRTCPSender);
229 return _REMB;
230}
231
232WebRtc_Word32
233RTCPSender::SetREMBStatus(const bool enable)
234{
235 CriticalSectionScoped lock(_criticalSectionRTCPSender);
236 _REMB = enable;
237 return 0;
238}
239
240WebRtc_Word32
241RTCPSender::SetREMBData(const WebRtc_UWord32 bitrate,
242 const WebRtc_UWord8 numberOfSSRC,
243 const WebRtc_UWord32* SSRC)
244{
245 CriticalSectionScoped lock(_criticalSectionRTCPSender);
246 _rembBitrate = bitrate;
247
248 if(_sizeRembSSRC < numberOfSSRC)
249 {
250 delete [] _rembSSRC;
251 _rembSSRC = new WebRtc_UWord32[numberOfSSRC];
252 _sizeRembSSRC = numberOfSSRC;
253 }
254
255 _lengthRembSSRC = numberOfSSRC;
256 for (int i = 0; i < numberOfSSRC; i++)
257 {
258 _rembSSRC[i] = SSRC[i];
259 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000260 _sendREMB = true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000261 return 0;
262}
263
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000264bool RTCPSender::SetRemoteBitrateObserver(RtpRemoteBitrateObserver* observer) {
265 CriticalSectionScoped lock(_criticalSectionRTCPSender);
266 if (observer && _bitrate_observer) {
267 return false;
268 }
269 _bitrate_observer = observer;
270 return true;
271}
272
273void RTCPSender::UpdateRemoteBitrateEstimate(unsigned int target_bitrate) {
274 CriticalSectionScoped lock(_criticalSectionRTCPSender);
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000275 if (_bitrate_observer) {
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000276 _bitrate_observer->OnReceiveBitrateChanged(_remoteSSRC, target_bitrate);
277 }
278}
279
mflodman@webrtc.orgf7b60782012-02-16 14:50:24 +0000280void RTCPSender::ReceivedRemb(unsigned int estimated_bitrate) {
281 CriticalSectionScoped lock(_criticalSectionRTCPSender);
282 if (_bitrate_observer) {
283 _bitrate_observer->OnReceivedRemb(estimated_bitrate);
284 }
285}
286
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000287bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000288RTCPSender::TMMBR() const
289{
290 CriticalSectionScoped lock(_criticalSectionRTCPSender);
291 return _TMMBR;
292}
293
294WebRtc_Word32
295RTCPSender::SetTMMBRStatus(const bool enable)
296{
297 CriticalSectionScoped lock(_criticalSectionRTCPSender);
298 _TMMBR = enable;
299 return 0;
300}
301
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000302bool
303RTCPSender::IJ() const
304{
305 CriticalSectionScoped lock(_criticalSectionRTCPSender);
306 return _IJ;
307}
308
309WebRtc_Word32
310RTCPSender::SetIJStatus(const bool enable)
311{
312 CriticalSectionScoped lock(_criticalSectionRTCPSender);
313 _IJ = enable;
314 return 0;
315}
316
niklase@google.com470e71d2011-07-07 08:21:25 +0000317void
318RTCPSender::SetSSRC( const WebRtc_UWord32 ssrc)
319{
320 CriticalSectionScoped lock(_criticalSectionRTCPSender);
321
322 if(_SSRC != 0)
323 {
324 // not first SetSSRC, probably due to a collision
325 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000326 // make sure that we send a RTP packet
327 _nextTimeToSendRTCP = _clock.GetTimeInMS() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000328 }
329 _SSRC = ssrc;
330}
331
332WebRtc_Word32
333RTCPSender::SetRemoteSSRC( const WebRtc_UWord32 ssrc)
334{
335 CriticalSectionScoped lock(_criticalSectionRTCPSender);
336 _remoteSSRC = ssrc;
337 _remoteRateControl.Reset();
338 return 0;
339}
340
341WebRtc_Word32
342RTCPSender::SetCameraDelay(const WebRtc_Word32 delayMS)
343{
344 CriticalSectionScoped lock(_criticalSectionRTCPSender);
345 if(delayMS > 1000 || delayMS < -1000)
346 {
347 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
348 return -1;
349 }
350 _cameraDelayMS = delayMS;
351 return 0;
352}
353
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000354WebRtc_Word32 RTCPSender::CNAME(char cName[RTCP_CNAME_SIZE]) {
355 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000356 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000357 cName[RTCP_CNAME_SIZE - 1] = 0;
358 strncpy(cName, _CNAME, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000359 return 0;
360}
361
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000362WebRtc_Word32 RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000363 if (!cName)
364 return -1;
365
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000366 CriticalSectionScoped lock(_criticalSectionRTCPSender);
367 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
368 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
369 return 0;
370}
371
372WebRtc_Word32 RTCPSender::AddMixedCNAME(const WebRtc_UWord32 SSRC,
373 const char cName[RTCP_CNAME_SIZE]) {
374 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000375 CriticalSectionScoped lock(_criticalSectionRTCPSender);
376 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
377 return -1;
378 }
379 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000380 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
381 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000382 _csrcCNAMEs[SSRC] = ptr;
383 return 0;
384}
385
386WebRtc_Word32 RTCPSender::RemoveMixedCNAME(const WebRtc_UWord32 SSRC) {
387 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000388 std::map<WebRtc_UWord32, RTCPCnameInformation*>::iterator it =
389 _csrcCNAMEs.find(SSRC);
390
391 if (it == _csrcCNAMEs.end()) {
392 return -1;
393 }
394 delete it->second;
395 _csrcCNAMEs.erase(it);
396 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000397}
398
399bool
400RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
401{
402/*
403 For audio we use a fix 5 sec interval
404
405 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
406 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
407
408
409From RFC 3550
410
411 MAX RTCP BW is 5% if the session BW
412 A send report is approximately 65 bytes inc CNAME
413 A report report is approximately 28 bytes
414
415 The RECOMMENDED value for the reduced minimum in seconds is 360
416 divided by the session bandwidth in kilobits/second. This minimum
417 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
418
419 If the participant has not yet sent an RTCP packet (the variable
420 initial is true), the constant Tmin is set to 2.5 seconds, else it
421 is set to 5 seconds.
422
423 The interval between RTCP packets is varied randomly over the
424 range [0.5,1.5] times the calculated interval to avoid unintended
425 synchronization of all participants
426
427 if we send
428 If the participant is a sender (we_sent true), the constant C is
429 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
430 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
431 number of senders.
432
433 if we receive only
434 If we_sent is not true, the constant C is set
435 to the average RTCP packet size divided by 75% of the RTCP
436 bandwidth. The constant n is set to the number of receivers
437 (members - senders). If the number of senders is greater than
438 25%, senders and receivers are treated together.
439
440 reconsideration NOT required for peer-to-peer
441 "timer reconsideration" is
442 employed. This algorithm implements a simple back-off mechanism
443 which causes users to hold back RTCP packet transmission if the
444 group sizes are increasing.
445
446 n = number of members
447 C = avg_size/(rtcpBW/4)
448
449 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
450
451 4. The calculated interval T is set to a number uniformly distributed
452 between 0.5 and 1.5 times the deterministic calculated interval.
453
454 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
455 for the fact that the timer reconsideration algorithm converges to
456 a value of the RTCP bandwidth below the intended average
457*/
458
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000459 WebRtc_UWord32 now = _clock.GetTimeInMS();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000460
461 CriticalSectionScoped lock(_criticalSectionRTCPSender);
462
niklase@google.com470e71d2011-07-07 08:21:25 +0000463 if(_method == kRtcpOff)
464 {
465 return false;
466 }
467
niklase@google.com470e71d2011-07-07 08:21:25 +0000468 if(!_audio && sendKeyframeBeforeRTP)
469 {
470 // for video key-frames we want to send the RTCP before the large key-frame
471 // if we have a 100 ms margin
472 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
473 }
474
475 if(now > _nextTimeToSendRTCP)
476 {
477 return true;
478
479 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
480 {
481 // wrap
482 return true;
483 }
484 return false;
485}
486
487WebRtc_UWord32
488RTCPSender::LastSendReport( WebRtc_UWord32& lastRTCPTime)
489{
490 CriticalSectionScoped lock(_criticalSectionRTCPSender);
491
492 lastRTCPTime = _lastRTCPTime[0];
493 return _lastSendReport[0];
494}
495
496WebRtc_UWord32
497RTCPSender::SendTimeOfSendReport(const WebRtc_UWord32 sendReport)
498{
499 CriticalSectionScoped lock(_criticalSectionRTCPSender);
500
501 // This is only saved when we are the sender
502 if((_lastSendReport[0] == 0) || (sendReport == 0))
503 {
504 return 0; // will be ignored
505 } else
506 {
507 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
508 {
509 if( _lastSendReport[i] == sendReport)
510 {
511 return _lastRTCPTime[i];
512 }
513 }
514 }
515 return 0;
516}
517
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000518WebRtc_Word32 RTCPSender::AddReportBlock(const WebRtc_UWord32 SSRC,
519 const RTCPReportBlock* reportBlock) {
520 if (reportBlock == NULL) {
521 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
522 "%s invalid argument", __FUNCTION__);
523 return -1;
524 }
525 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000526
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000527 if (_reportBlocks.size() >= RTCP_MAX_REPORT_BLOCKS) {
528 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
529 "%s invalid argument", __FUNCTION__);
530 return -1;
531 }
532 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
533 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
534 _reportBlocks[SSRC] = copyReportBlock;
535 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000536}
537
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000538WebRtc_Word32 RTCPSender::RemoveReportBlock(const WebRtc_UWord32 SSRC) {
539 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000540
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000541 std::map<WebRtc_UWord32, RTCPReportBlock*>::iterator it =
542 _reportBlocks.find(SSRC);
543
544 if (it == _reportBlocks.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000545 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000546 }
547 delete it->second;
548 _reportBlocks.erase(it);
549 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000550}
551
552WebRtc_Word32
553RTCPSender::BuildSR(WebRtc_UWord8* rtcpbuffer,
554 WebRtc_UWord32& pos,
555 const WebRtc_UWord32 NTPsec,
556 const WebRtc_UWord32 NTPfrac,
557 const RTCPReportBlock* received)
558{
559 // sanity
560 if(pos + 52 >= IP_PACKET_SIZE)
561 {
562 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
563 return -2;
564 }
565 WebRtc_UWord32 RTPtime;
566 WebRtc_UWord32 BackTimedNTPsec;
567 WebRtc_UWord32 BackTimedNTPfrac;
568
569 WebRtc_UWord32 posNumberOfReportBlocks = pos;
570 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
571
572 // Sender report
573 rtcpbuffer[pos++]=(WebRtc_UWord8)200;
574
575 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
576 {
577 // shift old
578 _lastSendReport[i+1] = _lastSendReport[i];
579 _lastRTCPTime[i+1] =_lastRTCPTime[i];
580 }
581
582 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac); // before video cam compensation
583
584 if(_cameraDelayMS >= 0)
585 {
586 // fraction of a second as an unsigned word32 4.294 967 296E9
587 WebRtc_UWord32 cameraDelayFixFrac = (WebRtc_UWord32)_cameraDelayMS* 4294967; // note camera delay can't be larger than +/-1000ms
588 if(NTPfrac > cameraDelayFixFrac)
589 {
590 // no problem just reduce the fraction part
591 BackTimedNTPfrac = NTPfrac - cameraDelayFixFrac;
592 BackTimedNTPsec = NTPsec;
593 } else
594 {
595 // we need to reduce the sec and add that sec to the frac
596 BackTimedNTPsec = NTPsec - 1;
597 BackTimedNTPfrac = 0xffffffff - (cameraDelayFixFrac - NTPfrac);
598 }
599 } else
600 {
601 // fraction of a second as an unsigned word32 4.294 967 296E9
602 WebRtc_UWord32 cameraDelayFixFrac = (WebRtc_UWord32)(-_cameraDelayMS)* 4294967; // note camera delay can't be larger than +/-1000ms
603 if(NTPfrac > 0xffffffff - cameraDelayFixFrac)
604 {
605 // we need to add the sec and add that sec to the frac
606 BackTimedNTPsec = NTPsec + 1;
607 BackTimedNTPfrac = cameraDelayFixFrac + NTPfrac; // this will wrap but that is ok
608 } else
609 {
610 // no problem just add the fraction part
611 BackTimedNTPsec = NTPsec;
612 BackTimedNTPfrac = NTPfrac + cameraDelayFixFrac;
613 }
614 }
615 _lastSendReport[0] = (BackTimedNTPsec <<16) + (BackTimedNTPfrac >> 16);
616
617 // RTP timestamp
618 // This should have a ramdom start value added
619 // RTP is counted from NTP not the acctual RTP
620 // This reflects the perfect RTP time
621 // we solve this by initiating RTP to our NTP :)
622
623 WebRtc_UWord32 freqHz = 90000; // For video
624 if(_audio)
625 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000626 freqHz = _rtpRtcp.CurrentSendFrequencyHz();
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000627 RTPtime = ModuleRTPUtility::GetCurrentRTP(&_clock, freqHz);
niklase@google.com470e71d2011-07-07 08:21:25 +0000628 }
629 else // video
630 {
631 // used to be (WebRtc_UWord32)(((float)BackTimedNTPfrac/(float)FRAC)* 90000)
632 WebRtc_UWord32 tmp = 9*(BackTimedNTPfrac/429496);
633 RTPtime = BackTimedNTPsec*freqHz + tmp;
634 }
635
636
637
638
639 // Add sender data
640 // Save for our length field
641 pos++;
642 pos++;
643
644 // Add our own SSRC
645 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
646 pos += 4;
647 // NTP
648 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, BackTimedNTPsec);
649 pos += 4;
650 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, BackTimedNTPfrac);
651 pos += 4;
652 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
653 pos += 4;
654
655 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000656 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000657 pos += 4;
658
659 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000660 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000661 pos += 4;
662
663 WebRtc_UWord8 numberOfReportBlocks = 0;
664 WebRtc_Word32 retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
665 if(retVal < 0)
666 {
667 //
668 return retVal ;
669 }
670 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
671
672 WebRtc_UWord16 len = WebRtc_UWord16((pos/4) -1);
673 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
674 return 0;
675}
676
677
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000678WebRtc_Word32 RTCPSender::BuildSDEC(WebRtc_UWord8* rtcpbuffer,
679 WebRtc_UWord32& pos) {
680 size_t lengthCname = strlen(_CNAME);
681 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000682
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000683 // sanity
684 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
685 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
686 "%s invalid argument", __FUNCTION__);
687 return -2;
688 }
689 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000690
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000691 // We always need to add SDES CNAME
692 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(0x80 + 1 + _csrcCNAMEs.size());
693 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000694
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000695 // handle SDES length later on
696 WebRtc_UWord32 SDESLengthPos = pos;
697 pos++;
698 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000699
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000700 // Add our own SSRC
701 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
702 pos += 4;
703
704 // CNAME = 1
705 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(1);
706
707 //
708 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(lengthCname);
709
710 WebRtc_UWord16 SDESLength = 10;
711
712 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
713 pos += lengthCname;
714 SDESLength += (WebRtc_UWord16)lengthCname;
715
716 WebRtc_UWord16 padding = 0;
717 // We must have a zero field even if we have an even multiple of 4 bytes
718 if ((pos % 4) == 0) {
719 padding++;
720 rtcpbuffer[pos++]=0;
721 }
722 while ((pos % 4) != 0) {
723 padding++;
724 rtcpbuffer[pos++]=0;
725 }
726 SDESLength += padding;
727
728 std::map<WebRtc_UWord32, RTCPUtility::RTCPCnameInformation*>::iterator it =
729 _csrcCNAMEs.begin();
730
731 for(; it != _csrcCNAMEs.end(); it++) {
732 RTCPCnameInformation* cname = it->second;
733 WebRtc_UWord32 SSRC = it->first;
734
735 // Add SSRC
736 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000737 pos += 4;
738
739 // CNAME = 1
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000740 rtcpbuffer[pos++] = static_cast<WebRtc_UWord8>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000741
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000742 size_t length = strlen(cname->name);
743 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000744
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000745 rtcpbuffer[pos++]= static_cast<WebRtc_UWord8>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000746 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000747
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000748 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000749
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000750 pos += length;
751 SDESLength += length;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000752 WebRtc_UWord16 padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000753
754 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000755 if((pos % 4) == 0){
756 padding++;
757 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000758 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000759 while((pos % 4) != 0){
760 padding++;
761 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000762 }
763 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000764 }
765 // in 32-bit words minus one and we don't count the header
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000766 WebRtc_UWord16 buffer_length = (SDESLength / 4) - 1;
767 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos,
768 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000769 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000770}
771
772WebRtc_Word32
773RTCPSender::BuildRR(WebRtc_UWord8* rtcpbuffer,
774 WebRtc_UWord32& pos,
775 const WebRtc_UWord32 NTPsec,
776 const WebRtc_UWord32 NTPfrac,
777 const RTCPReportBlock* received)
778{
779 // sanity one block
780 if(pos + 32 >= IP_PACKET_SIZE)
781 {
782 return -2;
783 }
784 WebRtc_UWord32 posNumberOfReportBlocks = pos;
785
786 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
787 rtcpbuffer[pos++]=(WebRtc_UWord8)201;
788
789 // Save for our length field
790 pos++;
791 pos++;
792
793 // Add our own SSRC
794 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
795 pos += 4;
796
797 WebRtc_UWord8 numberOfReportBlocks = 0;
798 WebRtc_Word32 retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
799 if(retVal < 0)
800 {
801 return retVal;
802 }
803 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
804
805 WebRtc_UWord16 len = WebRtc_UWord16((pos)/4 -1);
806 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
807 return 0;
808}
809
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000810// From RFC 5450: Transmission Time Offsets in RTP Streams.
811// 0 1 2 3
812// 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
813// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
814// hdr |V=2|P| RC | PT=IJ=195 | length |
815// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
816// | inter-arrival jitter |
817// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
818// . .
819// . .
820// . .
821// | inter-arrival jitter |
822// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
823//
824// If present, this RTCP packet must be placed after a receiver report
825// (inside a compound RTCP packet), and MUST have the same value for RC
826// (reception report count) as the receiver report.
827
828WebRtc_Word32
829RTCPSender::BuildExtendedJitterReport(
830 WebRtc_UWord8* rtcpbuffer,
831 WebRtc_UWord32& pos,
832 const WebRtc_UWord32 jitterTransmissionTimeOffset)
833{
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000834 if (_reportBlocks.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000835 {
836 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
837 return 0;
838 }
839
840 // sanity
841 if(pos + 8 >= IP_PACKET_SIZE)
842 {
843 return -2;
844 }
845 // add picture loss indicator
846 WebRtc_UWord8 RC = 1;
847 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + RC;
848 rtcpbuffer[pos++]=(WebRtc_UWord8)195;
849
850 // Used fixed length of 2
851 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
852 rtcpbuffer[pos++]=(WebRtc_UWord8)(1);
853
854 // Add inter-arrival jitter
855 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
856 jitterTransmissionTimeOffset);
857 pos += 4;
858 return 0;
859}
860
niklase@google.com470e71d2011-07-07 08:21:25 +0000861WebRtc_Word32
862RTCPSender::BuildPLI(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
863{
864 // sanity
865 if(pos + 12 >= IP_PACKET_SIZE)
866 {
867 return -2;
868 }
869 // add picture loss indicator
870 WebRtc_UWord8 FMT = 1;
871 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
872 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
873
874 //Used fixed length of 2
875 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
876 rtcpbuffer[pos++]=(WebRtc_UWord8)(2);
877
878 // Add our own SSRC
879 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
880 pos += 4;
881
882 // Add the remote SSRC
883 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
884 pos += 4;
885 return 0;
886}
887
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000888WebRtc_Word32 RTCPSender::BuildFIR(WebRtc_UWord8* rtcpbuffer,
889 WebRtc_UWord32& pos,
890 bool repeat) {
891 // sanity
892 if(pos + 20 >= IP_PACKET_SIZE) {
893 return -2;
894 }
895 if (!repeat) {
896 _sequenceNumberFIR++; // do not increase if repetition
897 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000898
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000899 // add full intra request indicator
900 WebRtc_UWord8 FMT = 4;
901 rtcpbuffer[pos++] = (WebRtc_UWord8)0x80 + FMT;
902 rtcpbuffer[pos++] = (WebRtc_UWord8)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000903
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000904 //Length of 4
905 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
906 rtcpbuffer[pos++] = (WebRtc_UWord8)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000907
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000908 // Add our own SSRC
909 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
910 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000911
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000912 // RFC 5104 4.3.1.2. Semantics
913 // SSRC of media source
914 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
915 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
916 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
917 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000918
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000919 // Additional Feedback Control Information (FCI)
920 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
921 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000922
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000923 rtcpbuffer[pos++] = (WebRtc_UWord8)(_sequenceNumberFIR);
924 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
925 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
926 rtcpbuffer[pos++] = (WebRtc_UWord8)0;
927 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000928}
929
930/*
931 0 1 2 3
932 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
933 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
934 | First | Number | PictureID |
935 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
936*/
937WebRtc_Word32
938RTCPSender::BuildSLI(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos, const WebRtc_UWord8 pictureID)
939{
940 // sanity
941 if(pos + 16 >= IP_PACKET_SIZE)
942 {
943 return -2;
944 }
945 // add slice loss indicator
946 WebRtc_UWord8 FMT = 2;
947 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
948 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
949
950 //Used fixed length of 3
951 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
952 rtcpbuffer[pos++]=(WebRtc_UWord8)(3);
953
954 // Add our own SSRC
955 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
956 pos += 4;
957
958 // Add the remote SSRC
959 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
960 pos += 4;
961
962 // Add first, number & picture ID 6 bits
963 // first = 0, 13 - bits
964 // number = 0x1fff, 13 - bits only ones for now
965 WebRtc_UWord32 sliField = (0x1fff << 6)+ (0x3f & pictureID);
966 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
967 pos += 4;
968 return 0;
969}
970
971/*
972 0 1 2 3
973 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
974 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
975 | PB |0| Payload Type| Native RPSI bit string |
976 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
977 | defined per codec ... | Padding (0) |
978 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
979*/
980/*
981* Note: not generic made for VP8
982*/
983WebRtc_Word32
984RTCPSender::BuildRPSI(WebRtc_UWord8* rtcpbuffer,
985 WebRtc_UWord32& pos,
986 const WebRtc_UWord64 pictureID,
987 const WebRtc_UWord8 payloadType)
988{
989 // sanity
990 if(pos + 24 >= IP_PACKET_SIZE)
991 {
992 return -2;
993 }
994 // add Reference Picture Selection Indication
995 WebRtc_UWord8 FMT = 3;
996 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
997 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
998
999 // calc length
1000 WebRtc_UWord32 bitsRequired = 7;
1001 WebRtc_UWord8 bytesRequired = 1;
1002 while((pictureID>>bitsRequired) > 0)
1003 {
1004 bitsRequired += 7;
1005 bytesRequired++;
1006 }
1007
1008 WebRtc_UWord8 size = 3;
1009 if(bytesRequired > 6)
1010 {
1011 size = 5;
1012 } else if(bytesRequired > 2)
1013 {
1014 size = 4;
1015 }
1016 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1017 rtcpbuffer[pos++]=size;
1018
1019 // Add our own SSRC
1020 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1021 pos += 4;
1022
1023 // Add the remote SSRC
1024 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1025 pos += 4;
1026
1027 // calc padding length
1028 WebRtc_UWord8 paddingBytes = 4-((2+bytesRequired)%4);
1029 if(paddingBytes == 4)
1030 {
1031 paddingBytes = 0;
1032 }
1033 // add padding length in bits
1034 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1035 pos++;
1036
1037 // add payload type
1038 rtcpbuffer[pos] = payloadType;
1039 pos++;
1040
1041 // add picture ID
1042 for(int i = bytesRequired-1; i > 0; i--)
1043 {
1044 rtcpbuffer[pos] = 0x80 | WebRtc_UWord8(pictureID >> (i*7));
1045 pos++;
1046 }
1047 // add last byte of picture ID
1048 rtcpbuffer[pos] = WebRtc_UWord8(pictureID & 0x7f);
1049 pos++;
1050
1051 // add padding
1052 for(int j = 0; j <paddingBytes; j++)
1053 {
1054 rtcpbuffer[pos] = 0;
1055 pos++;
1056 }
1057 return 0;
1058}
1059
1060WebRtc_Word32
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001061RTCPSender::BuildREMB(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1062{
1063 // sanity
1064 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1065 {
1066 return -2;
1067 }
1068 // add application layer feedback
1069 WebRtc_UWord8 FMT = 15;
1070 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1071 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
1072
1073 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1074 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1075
1076 // Add our own SSRC
1077 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1078 pos += 4;
1079
1080 // Remote SSRC must be 0
1081 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1082 pos += 4;
1083
1084 rtcpbuffer[pos++]='R';
1085 rtcpbuffer[pos++]='E';
1086 rtcpbuffer[pos++]='M';
1087 rtcpbuffer[pos++]='B';
1088
1089 rtcpbuffer[pos++] = _lengthRembSSRC;
1090 // 6 bit Exp
1091 // 18 bit mantissa
1092 WebRtc_UWord8 brExp = 0;
1093 for(WebRtc_UWord32 i=0; i<64; i++)
1094 {
1095 if(_rembBitrate <= ((WebRtc_UWord32)262143 << i))
1096 {
1097 brExp = i;
1098 break;
1099 }
1100 }
1101 const WebRtc_UWord32 brMantissa = (_rembBitrate >> brExp);
1102 rtcpbuffer[pos++]=(WebRtc_UWord8)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1103 rtcpbuffer[pos++]=(WebRtc_UWord8)(brMantissa >> 8);
1104 rtcpbuffer[pos++]=(WebRtc_UWord8)(brMantissa);
1105
1106 for (int i = 0; i < _lengthRembSSRC; i++)
1107 {
1108 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1109 pos += 4;
1110 }
1111 return 0;
1112}
1113
1114WebRtc_UWord32
1115RTCPSender::CalculateNewTargetBitrate(WebRtc_UWord32 RTT)
1116{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001117 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001118 WebRtc_UWord32 target_bitrate =
stefan@webrtc.org439be292012-02-16 14:45:37 +00001119 _remoteRateControl.UpdateBandwidthEstimate(RTT, _clock.GetTimeInMS());
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001120 _tmmbr_Send = target_bitrate / 1000;
1121 return target_bitrate;
1122}
1123
stefan@webrtc.org439be292012-02-16 14:45:37 +00001124WebRtc_UWord32 RTCPSender::LatestBandwidthEstimate() const {
1125 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1126 return _remoteRateControl.LatestEstimate();
1127}
1128
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001129bool
stefan@webrtc.org439be292012-02-16 14:45:37 +00001130RTCPSender::ValidBitrateEstimate() const {
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001131 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1132 return _remoteRateControl.ValidEstimate();
1133}
1134
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001135WebRtc_Word32
1136RTCPSender::BuildTMMBR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001137{
1138 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1139 // If the sender is an owner of the TMMBN -> send TMMBR
1140 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1141
niklase@google.com470e71d2011-07-07 08:21:25 +00001142 // get current bounding set from RTCP receiver
1143 bool tmmbrOwner = false;
1144 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet(); // store in candidateSet, allocates one extra slot
1145
1146 // holding _criticalSectionRTCPSender while calling RTCPreceiver which will accuire _criticalSectionRTCPReceiver
1147 // is a potental deadlock but since RTCPreceiver is not doing the revese we should be fine
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001148 WebRtc_Word32 lengthOfBoundingSet = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001149
1150 if(lengthOfBoundingSet > 0)
1151 {
1152 for (WebRtc_Word32 i = 0; i < lengthOfBoundingSet; i++)
1153 {
1154 if( candidateSet->ptrTmmbrSet[i] == _tmmbr_Send &&
1155 candidateSet->ptrPacketOHSet[i] == _packetOH_Send)
1156 {
1157 // do not send the same tuple
1158 return 0;
1159 }
1160 }
1161 if(!tmmbrOwner)
1162 {
1163 // use received bounding set as candidate set
1164 // add current tuple
1165 candidateSet->ptrTmmbrSet[lengthOfBoundingSet] = _tmmbr_Send;
1166 candidateSet->ptrPacketOHSet[lengthOfBoundingSet] = _packetOH_Send;
1167 candidateSet->ptrSsrcSet[lengthOfBoundingSet] = _SSRC;
1168 int numCandidates = lengthOfBoundingSet+ 1;
1169
1170 // find bounding set
1171 TMMBRSet* boundingSet = NULL;
1172 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1173 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1174 {
1175 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1176 }
1177 if(!tmmbrOwner)
1178 {
1179 // did not enter bounding set, no meaning to send this request
1180 return 0;
1181 }
1182 }
1183 }
1184
1185 if(_tmmbr_Send)
1186 {
1187 // sanity
1188 if(pos + 20 >= IP_PACKET_SIZE)
1189 {
1190 return -2;
1191 }
1192 // add TMMBR indicator
1193 WebRtc_UWord8 FMT = 3;
1194 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1195 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1196
1197 //Length of 4
1198 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1199 rtcpbuffer[pos++]=(WebRtc_UWord8)(4);
1200
1201 // Add our own SSRC
1202 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1203 pos += 4;
1204
1205 // RFC 5104 4.2.1.2. Semantics
1206
1207 // SSRC of media source
1208 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1209 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1210 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1211 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1212
1213 // Additional Feedback Control Information (FCI)
1214 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1215 pos += 4;
1216
1217 WebRtc_UWord32 bitRate = _tmmbr_Send*1000;
1218 WebRtc_UWord32 mmbrExp = 0;
1219 for(WebRtc_UWord32 i=0;i<64;i++)
1220 {
1221 if(bitRate <= ((WebRtc_UWord32)131071 << i))
1222 {
1223 mmbrExp = i;
1224 break;
1225 }
1226 }
1227 WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp);
1228
1229 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1230 rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);
1231 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1232 rtcpbuffer[pos++]=(WebRtc_UWord8)(_packetOH_Send);
1233 }
1234 return 0;
1235}
1236
1237WebRtc_Word32
1238RTCPSender::BuildTMMBN(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1239{
1240 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1241 if(boundingSet == NULL)
1242 {
1243 return -1;
1244 }
1245 // sanity
1246 if(pos + 12 + boundingSet->lengthOfSet*8 >= IP_PACKET_SIZE)
1247 {
1248 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1249 return -2;
1250 }
1251 WebRtc_UWord8 FMT = 4;
1252 // add TMMBN indicator
1253 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1254 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1255
1256 //Add length later
1257 int posLength = pos;
1258 pos++;
1259 pos++;
1260
1261 // Add our own SSRC
1262 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1263 pos += 4;
1264
1265 // RFC 5104 4.2.2.2. Semantics
1266
1267 // SSRC of media source
1268 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1269 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1270 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1271 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1272
1273 // Additional Feedback Control Information (FCI)
1274 int numBoundingSet = 0;
1275 for(WebRtc_UWord32 n=0; n< boundingSet->lengthOfSet; n++)
1276 {
1277 if (boundingSet->ptrTmmbrSet[n] > 0)
1278 {
1279 WebRtc_UWord32 tmmbrSSRC = boundingSet->ptrSsrcSet[n];
1280 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1281 pos += 4;
1282
1283 WebRtc_UWord32 bitRate = boundingSet->ptrTmmbrSet[n] * 1000;
1284 WebRtc_UWord32 mmbrExp = 0;
1285 for(int i=0; i<64; i++)
1286 {
1287 if(bitRate <= ((WebRtc_UWord32)131071 << i))
1288 {
1289 mmbrExp = i;
1290 break;
1291 }
1292 }
1293 WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp);
1294 WebRtc_UWord32 measuredOH = boundingSet->ptrPacketOHSet[n];
1295
1296 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1297 rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);
1298 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1299 rtcpbuffer[pos++]=(WebRtc_UWord8)(measuredOH);
1300 numBoundingSet++;
1301 }
1302 }
1303 WebRtc_UWord16 length= (WebRtc_UWord16)(2+2*numBoundingSet);
1304 rtcpbuffer[posLength++]=(WebRtc_UWord8)(length>>8);
1305 rtcpbuffer[posLength]=(WebRtc_UWord8)(length);
1306 return 0;
1307}
1308
1309WebRtc_Word32
1310RTCPSender::BuildAPP(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1311{
1312 // sanity
1313 if(_appData == NULL)
1314 {
1315 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1316 return -1;
1317 }
1318 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1319 {
1320 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1321 return -2;
1322 }
1323 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + _appSubType;
1324
1325 // Add APP ID
1326 rtcpbuffer[pos++]=(WebRtc_UWord8)204;
1327
1328 WebRtc_UWord16 length = (_appLength>>2) + 2; // include SSRC and name
1329 rtcpbuffer[pos++]=(WebRtc_UWord8)(length>>8);
1330 rtcpbuffer[pos++]=(WebRtc_UWord8)(length);
1331
1332 // Add our own SSRC
1333 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1334 pos += 4;
1335
1336 // Add our application name
1337 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1338 pos += 4;
1339
1340 // Add the data
1341 memcpy(rtcpbuffer +pos, _appData,_appLength);
1342 pos += _appLength;
1343 return 0;
1344}
1345
1346WebRtc_Word32
1347RTCPSender::BuildNACK(WebRtc_UWord8* rtcpbuffer,
1348 WebRtc_UWord32& pos,
1349 const WebRtc_Word32 nackSize,
1350 const WebRtc_UWord16* nackList)
1351{
1352 // sanity
1353 if(pos + 16 >= IP_PACKET_SIZE)
1354 {
1355 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1356 return -2;
1357 }
1358
1359 // int size, WebRtc_UWord16* nackList
1360 // add nack list
1361 WebRtc_UWord8 FMT = 1;
1362 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1363 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1364
1365 rtcpbuffer[pos++]=(WebRtc_UWord8) 0;
1366 int nackSizePos = pos;
1367 rtcpbuffer[pos++]=(WebRtc_UWord8)(3); //setting it to one kNACK signal as default
1368
1369 // Add our own SSRC
1370 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1371 pos += 4;
1372
1373 // Add the remote SSRC
1374 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1375 pos += 4;
1376
1377 // add the list
1378 int i = 0;
1379 int numOfNackFields = 0;
1380 while(nackSize > i && numOfNackFields < 253)
1381 {
1382 WebRtc_UWord16 nack = nackList[i];
1383 // put dow our sequence number
1384 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, nack);
1385 pos += 2;
1386
1387 i++;
1388 numOfNackFields++;
1389 if(nackSize > i)
1390 {
1391 bool moreThan16Away = (WebRtc_UWord16(nack+16) < nackList[i])?true: false;
1392 if(!moreThan16Away)
1393 {
1394 // check for a wrap
1395 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1396 {
1397 // wrap
1398 moreThan16Away = true;
1399 }
1400 }
1401 if(moreThan16Away)
1402 {
1403 // next is more than 16 away
1404 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1405 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1406 } else
1407 {
1408 // build our bitmask
1409 WebRtc_UWord16 bitmask = 0;
1410
1411 bool within16Away = (WebRtc_UWord16(nack+16) > nackList[i])?true: false;
1412 if(within16Away)
1413 {
1414 // check for a wrap
1415 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1416 {
1417 // wrap
1418 within16Away = false;
1419 }
1420 }
1421
1422 while( nackSize > i && within16Away)
1423 {
1424 WebRtc_Word16 shift = (nackList[i]-nack)-1;
1425 assert(!(shift > 15) && !(shift < 0));
1426
1427 bitmask += (1<< shift);
1428 i++;
1429 if(nackSize > i)
1430 {
1431 within16Away = (WebRtc_UWord16(nack+16) > nackList[i])?true: false;
1432 if(within16Away)
1433 {
1434 // check for a wrap
1435 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1436 {
1437 // wrap
1438 within16Away = false;
1439 }
1440 }
1441 }
1442 }
1443 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, bitmask);
1444 pos += 2;
1445 }
1446 // sanity do we have room from one more 4 byte block?
1447 if(pos + 4 >= IP_PACKET_SIZE)
1448 {
1449 return -2;
1450 }
1451 } else
1452 {
1453 // no more in the list
1454 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1455 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1456 }
1457 }
1458 rtcpbuffer[nackSizePos]=(WebRtc_UWord8)(2+numOfNackFields);
1459 return 0;
1460}
1461
1462WebRtc_Word32
1463RTCPSender::BuildBYE(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1464{
1465 // sanity
1466 if(pos + 8 >= IP_PACKET_SIZE)
1467 {
1468 return -2;
1469 }
1470 if(_includeCSRCs)
1471 {
1472 // Add a bye packet
1473 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1474 rtcpbuffer[pos++]=(WebRtc_UWord8)203;
1475
1476 // length
1477 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1478 rtcpbuffer[pos++]=(WebRtc_UWord8)(1 + _CSRCs);
1479
1480 // Add our own SSRC
1481 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1482 pos += 4;
1483
1484 // add CSRCs
1485 for(int i = 0; i < _CSRCs; i++)
1486 {
1487 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1488 pos += 4;
1489 }
1490 } else
1491 {
1492 // Add a bye packet
1493 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1; // number of SSRC+CSRCs
1494 rtcpbuffer[pos++]=(WebRtc_UWord8)203;
1495
1496 // length
1497 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1498 rtcpbuffer[pos++]=(WebRtc_UWord8)1;
1499
1500 // Add our own SSRC
1501 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1502 pos += 4;
1503 }
1504 return 0;
1505}
1506
1507WebRtc_Word32
1508RTCPSender::BuildVoIPMetric(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1509{
1510 // sanity
1511 if(pos + 44 >= IP_PACKET_SIZE)
1512 {
1513 return -2;
1514 }
1515
1516 // Add XR header
1517 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
1518 rtcpbuffer[pos++]=(WebRtc_UWord8)207;
1519
1520 WebRtc_UWord32 XRLengthPos = pos;
1521
1522 // handle length later on
1523 pos++;
1524 pos++;
1525
1526 // Add our own SSRC
1527 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1528 pos += 4;
1529
1530 // Add a VoIP metrics block
1531 rtcpbuffer[pos++]=7;
1532 rtcpbuffer[pos++]=0;
1533 rtcpbuffer[pos++]=0;
1534 rtcpbuffer[pos++]=8;
1535
1536 // Add the remote SSRC
1537 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1538 pos += 4;
1539
1540 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1541 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1542 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1543 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1544
1545 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.burstDuration >> 8);
1546 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.burstDuration);
1547 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.gapDuration >> 8);
1548 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.gapDuration);
1549
1550 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.roundTripDelay >> 8);
1551 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.roundTripDelay);
1552 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.endSystemDelay >> 8);
1553 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.endSystemDelay);
1554
1555 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1556 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1557 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1558 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1559
1560 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1561 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1562 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1563 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1564
1565 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1566 rtcpbuffer[pos++] = 0; // reserved
1567 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBnominal >> 8);
1568 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBnominal);
1569
1570 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBmax >> 8);
1571 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBmax);
1572 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBabsMax >> 8);
1573 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBabsMax);
1574
1575 rtcpbuffer[XRLengthPos]=(WebRtc_UWord8)(0);
1576 rtcpbuffer[XRLengthPos+1]=(WebRtc_UWord8)(10);
1577 return 0;
1578}
1579
1580WebRtc_Word32
1581RTCPSender::SendRTCP(const WebRtc_UWord32 packetTypeFlags,
1582 const WebRtc_Word32 nackSize, // NACK
1583 const WebRtc_UWord16* nackList, // NACK
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001584 const bool repeat, // FIR
niklase@google.com470e71d2011-07-07 08:21:25 +00001585 const WebRtc_UWord64 pictureID) // SLI & RPSI
1586{
1587 WebRtc_UWord32 rtcpPacketTypeFlags = packetTypeFlags;
1588 WebRtc_UWord32 pos = 0;
1589 WebRtc_UWord8 rtcpbuffer[IP_PACKET_SIZE];
1590
niklase@google.com470e71d2011-07-07 08:21:25 +00001591 do // only to be able to use break :) (and the critsect must be inside its own scope)
1592 {
1593 // collect the received information
1594 RTCPReportBlock received;
1595 bool hasReceived = false;
1596 WebRtc_UWord32 NTPsec = 0;
1597 WebRtc_UWord32 NTPfrac = 0;
xians@webrtc.org8738d272011-11-25 13:43:53 +00001598 bool rtcpCompound = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001599 WebRtc_UWord32 jitterTransmissionOffset = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001600
xians@webrtc.org8738d272011-11-25 13:43:53 +00001601 {
1602 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1603 if(_method == kRtcpOff)
1604 {
1605 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1606 "%s invalid state", __FUNCTION__);
1607 return -1;
1608 }
1609 rtcpCompound = (_method == kRtcpCompound) ? true : false;
1610 }
1611
1612 if (rtcpCompound ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001613 rtcpPacketTypeFlags & kRtcpReport ||
1614 rtcpPacketTypeFlags & kRtcpSr ||
1615 rtcpPacketTypeFlags & kRtcpRr)
1616 {
1617 // get statistics from our RTPreceiver outside critsect
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001618 if(_rtpRtcp.ReportBlockStatistics(&received.fractionLost,
1619 &received.cumulativeLost,
1620 &received.extendedHighSeqNum,
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001621 &received.jitter,
1622 &jitterTransmissionOffset) == 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001623 {
1624 hasReceived = true;
1625
1626 WebRtc_UWord32 lastReceivedRRNTPsecs = 0;
1627 WebRtc_UWord32 lastReceivedRRNTPfrac = 0;
1628 WebRtc_UWord32 remoteSR = 0;
1629
1630 // ok even if we have not received a SR, we will send 0 in that case
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001631 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1632 lastReceivedRRNTPfrac,
1633 remoteSR);
niklase@google.com470e71d2011-07-07 08:21:25 +00001634
1635 // get our NTP as late as possible to avoid a race
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001636 _clock.CurrentNTP(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001637
1638 // Delay since last received report
1639 WebRtc_UWord32 delaySinceLastReceivedSR = 0;
1640 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
1641 {
1642 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1643 WebRtc_UWord32 now=NTPsec&0x0000FFFF;
1644 now <<=16;
1645 now += (NTPfrac&0xffff0000)>>16;
1646
1647 WebRtc_UWord32 receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
1648 receiveTime <<=16;
1649 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1650
1651 delaySinceLastReceivedSR = now-receiveTime;
1652 }
1653 received.delaySinceLastSR = delaySinceLastReceivedSR;
1654 received.lastSR = remoteSR;
1655 } else
1656 {
1657 // we need to send our NTP even if we dont have received any reports
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001658 _clock.CurrentNTP(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001659 }
1660 }
1661
1662 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1663
1664 if(_TMMBR ) // attach TMMBR to send and receive reports
1665 {
1666 rtcpPacketTypeFlags |= kRtcpTmmbr;
1667 }
1668 if(_appSend)
1669 {
1670 rtcpPacketTypeFlags |= kRtcpApp;
1671 _appSend = false;
1672 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001673 if(_REMB && _sendREMB)
1674 {
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +00001675 // Always attach REMB to SR if that is configured. Note that REMB is
1676 // only sent on one of the RTP modules in the REMB group.
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001677 rtcpPacketTypeFlags |= kRtcpRemb;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001678 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001679 if(_xrSendVoIPMetric)
1680 {
1681 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1682 _xrSendVoIPMetric = false;
1683 }
1684 if(_sendTMMBN) // set when having received a TMMBR
1685 {
1686 rtcpPacketTypeFlags |= kRtcpTmmbn;
1687 _sendTMMBN = false;
1688 }
1689
1690 if(_method == kRtcpCompound)
1691 {
1692 if(_sending)
1693 {
1694 rtcpPacketTypeFlags |= kRtcpSr;
1695 } else
1696 {
1697 rtcpPacketTypeFlags |= kRtcpRr;
1698 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001699 if (_IJ && hasReceived)
1700 {
1701 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1702 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001703 } else if(_method == kRtcpNonCompound)
1704 {
1705 if(rtcpPacketTypeFlags & kRtcpReport)
1706 {
1707 if(_sending)
1708 {
1709 rtcpPacketTypeFlags |= kRtcpSr;
1710 } else
1711 {
1712 rtcpPacketTypeFlags |= kRtcpRr;
1713 }
1714 }
1715 }
1716 if( rtcpPacketTypeFlags & kRtcpRr ||
1717 rtcpPacketTypeFlags & kRtcpSr)
1718 {
1719 // generate next time to send a RTCP report
1720 // seeded from RTP constructor
1721 WebRtc_Word32 random = rand() % 1000;
1722 WebRtc_Word32 timeToNext = RTCP_INTERVAL_AUDIO_MS;
1723
1724 if(_audio)
1725 {
1726 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
1727 }else
1728 {
1729 WebRtc_UWord32 minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1730 if(_sending)
1731 {
1732 // calc bw for video 360/sendBW in kbit/s
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001733 WebRtc_UWord32 sendBitrateKbit = 0;
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001734 WebRtc_UWord32 videoRate = 0;
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001735 WebRtc_UWord32 fecRate = 0;
1736 WebRtc_UWord32 nackRate = 0;
1737 _rtpRtcp.BitrateSent(&sendBitrateKbit,
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001738 &videoRate,
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001739 &fecRate,
1740 &nackRate);
1741 sendBitrateKbit /= 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001742 if(sendBitrateKbit != 0)
1743 {
1744 minIntervalMs = 360000/sendBitrateKbit;
1745 }
1746 }
1747 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1748 {
1749 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1750 }
1751 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1752 }
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001753 _nextTimeToSendRTCP = _clock.GetTimeInMS() + timeToNext;
niklase@google.com470e71d2011-07-07 08:21:25 +00001754 }
1755
1756 // if the data does not fitt in the packet we fill it as much as possible
1757 WebRtc_Word32 buildVal = 0;
1758
1759 if(rtcpPacketTypeFlags & kRtcpSr)
1760 {
1761 if(hasReceived)
1762 {
1763 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
1764 } else
1765 {
1766 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac);
1767 }
1768 if(buildVal == -1)
1769 {
1770 return -1; // error
1771
1772 }else if(buildVal == -2)
1773 {
1774 break; // out of buffer
1775 }
1776 buildVal = BuildSDEC(rtcpbuffer, pos);
1777 if(buildVal == -1)
1778 {
1779 return -1; // error
1780
1781 }else if(buildVal == -2)
1782 {
1783 break; // out of buffer
1784 }
1785
1786 }else if(rtcpPacketTypeFlags & kRtcpRr)
1787 {
1788 if(hasReceived)
1789 {
1790 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
1791 }else
1792 {
1793 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
1794 }
1795 if(buildVal == -1)
1796 {
1797 return -1; // error
1798
1799 }else if(buildVal == -2)
1800 {
1801 break; // out of buffer
1802 }
1803 // only of set
1804 if(_CNAME[0] != 0)
1805 {
1806 buildVal = BuildSDEC(rtcpbuffer, pos);
1807 if(buildVal == -1)
1808 {
1809 return -1; // error
1810 }
1811 }
1812 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001813 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1814 {
1815 // If present, this RTCP packet must be placed after a
1816 // receiver report.
1817 buildVal = BuildExtendedJitterReport(rtcpbuffer,
1818 pos,
1819 jitterTransmissionOffset);
1820 if(buildVal == -1)
1821 {
1822 return -1; // error
1823 }
1824 else if(buildVal == -2)
1825 {
1826 break; // out of buffer
1827 }
1828 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001829 if(rtcpPacketTypeFlags & kRtcpPli)
1830 {
1831 buildVal = BuildPLI(rtcpbuffer, pos);
1832 if(buildVal == -1)
1833 {
1834 return -1; // error
1835
1836 }else if(buildVal == -2)
1837 {
1838 break; // out of buffer
1839 }
1840 }
1841 if(rtcpPacketTypeFlags & kRtcpFir)
1842 {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +00001843 buildVal = BuildFIR(rtcpbuffer, pos, repeat);
niklase@google.com470e71d2011-07-07 08:21:25 +00001844 if(buildVal == -1)
1845 {
1846 return -1; // error
1847
1848 }else if(buildVal == -2)
1849 {
1850 break; // out of buffer
1851 }
1852 }
1853 if(rtcpPacketTypeFlags & kRtcpSli)
1854 {
1855 buildVal = BuildSLI(rtcpbuffer, pos, (WebRtc_UWord8)pictureID);
1856 if(buildVal == -1)
1857 {
1858 return -1; // error
1859
1860 }else if(buildVal == -2)
1861 {
1862 break; // out of buffer
1863 }
1864 }
1865 if(rtcpPacketTypeFlags & kRtcpRpsi)
1866 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001867 const WebRtc_Word8 payloadType = _rtpRtcp.SendPayloadType();
niklase@google.com470e71d2011-07-07 08:21:25 +00001868 if(payloadType == -1)
1869 {
1870 return -1;
1871 }
1872 buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (WebRtc_UWord8)payloadType);
1873 if(buildVal == -1)
1874 {
1875 return -1; // error
1876
1877 }else if(buildVal == -2)
1878 {
1879 break; // out of buffer
1880 }
1881 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001882 if(rtcpPacketTypeFlags & kRtcpRemb)
1883 {
1884 buildVal = BuildREMB(rtcpbuffer, pos);
1885 if(buildVal == -1)
1886 {
1887 return -1; // error
1888
1889 }else if(buildVal == -2)
1890 {
1891 break; // out of buffer
1892 }
1893 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001894 if(rtcpPacketTypeFlags & kRtcpBye)
1895 {
1896 buildVal = BuildBYE(rtcpbuffer, pos);
1897 if(buildVal == -1)
1898 {
1899 return -1; // error
1900
1901 }else if(buildVal == -2)
1902 {
1903 break; // out of buffer
1904 }
1905 }
1906 if(rtcpPacketTypeFlags & kRtcpApp)
1907 {
1908 buildVal = BuildAPP(rtcpbuffer, pos);
1909 if(buildVal == -1)
1910 {
1911 return -1; // error
1912
1913 }else if(buildVal == -2)
1914 {
1915 break; // out of buffer
1916 }
1917 }
1918 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1919 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001920 buildVal = BuildTMMBR(rtcpbuffer, pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001921 if(buildVal == -1)
1922 {
1923 return -1; // error
1924
1925 }else if(buildVal == -2)
1926 {
1927 break; // out of buffer
1928 }
1929 }
1930 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1931 {
1932 buildVal = BuildTMMBN(rtcpbuffer, pos);
1933 if(buildVal == -1)
1934 {
1935 return -1; // error
1936
1937 }else if(buildVal == -2)
1938 {
1939 break; // out of buffer
1940 }
1941 }
1942 if(rtcpPacketTypeFlags & kRtcpNack)
1943 {
1944 buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList);
1945 if(buildVal == -1)
1946 {
1947 return -1; // error
1948
1949 }else if(buildVal == -2)
1950 {
1951 break; // out of buffer
1952 }
1953 }
1954 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1955 {
1956 buildVal = BuildVoIPMetric(rtcpbuffer, pos);
1957 if(buildVal == -1)
1958 {
1959 return -1; // error
1960
1961 }else if(buildVal == -2)
1962 {
1963 break; // out of buffer
1964 }
1965 }
1966 }while (false);
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001967 // Sanity don't send empty packets.
1968 if (pos == 0)
1969 {
1970 return -1;
1971 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001972 return SendToNetwork(rtcpbuffer, (WebRtc_UWord16)pos);
1973}
1974
1975WebRtc_Word32
1976RTCPSender::SendToNetwork(const WebRtc_UWord8* dataBuffer,
1977 const WebRtc_UWord16 length)
1978{
1979 CriticalSectionScoped lock(_criticalSectionTransport);
1980 if(_cbTransport)
1981 {
1982 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1983 {
1984 return 0;
1985 }
1986 }
1987 return -1;
1988}
1989
1990WebRtc_Word32
1991RTCPSender::SetCSRCStatus(const bool include)
1992{
1993 _includeCSRCs = include;
1994 return 0;
1995}
1996
1997WebRtc_Word32
1998RTCPSender::SetCSRCs(const WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize],
1999 const WebRtc_UWord8 arrLength)
2000{
2001 if(arrLength > kRtpCsrcSize)
2002 {
2003 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2004 assert(false);
2005 return -1;
2006 }
2007
2008 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2009
2010 for(int i = 0; i < arrLength;i++)
2011 {
2012 _CSRC[i] = arrOfCSRC[i];
2013 }
2014 _CSRCs = arrLength;
2015 return 0;
2016}
2017
2018WebRtc_Word32
2019RTCPSender::SetApplicationSpecificData(const WebRtc_UWord8 subType,
2020 const WebRtc_UWord32 name,
2021 const WebRtc_UWord8* data,
2022 const WebRtc_UWord16 length)
2023{
2024 if(length %4 != 0)
2025 {
2026 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2027 return -1;
2028 }
2029 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2030
2031 if(_appData)
2032 {
2033 delete [] _appData;
2034 }
2035
2036 _appSend = true;
2037 _appSubType = subType;
2038 _appName = name;
2039 _appData = new WebRtc_UWord8[length];
2040 _appLength = length;
2041 memcpy(_appData, data, length);
2042 return 0;
2043}
2044
2045WebRtc_Word32
2046RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2047{
2048 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2049 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2050
2051 _xrSendVoIPMetric = true;
2052 return 0;
2053}
2054
2055// called under critsect _criticalSectionRTCPSender
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002056WebRtc_Word32 RTCPSender::AddReportBlocks(WebRtc_UWord8* rtcpbuffer,
2057 WebRtc_UWord32& pos,
2058 WebRtc_UWord8& numberOfReportBlocks,
2059 const RTCPReportBlock* received,
2060 const WebRtc_UWord32 NTPsec,
2061 const WebRtc_UWord32 NTPfrac) {
2062 // sanity one block
2063 if(pos + 24 >= IP_PACKET_SIZE) {
2064 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2065 "%s invalid argument", __FUNCTION__);
2066 return -1;
2067 }
2068 numberOfReportBlocks = _reportBlocks.size();
2069 if (received) {
2070 // add our multiple RR to numberOfReportBlocks
2071 numberOfReportBlocks++;
2072 }
2073 if (received) {
2074 // answer to the one that sends to me
2075 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac);
2076
2077 // Remote SSRC
2078 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
2079 pos += 4;
2080
2081 // fraction lost
2082 rtcpbuffer[pos++]=received->fractionLost;
2083
2084 // cumulative loss
2085 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2086 received->cumulativeLost);
2087 pos += 3;
2088 // extended highest seq_no, contain the highest sequence number received
2089 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2090 received->extendedHighSeqNum);
2091 pos += 4;
2092
2093 //Jitter
2094 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
2095 pos += 4;
2096
2097 // Last SR timestamp, our NTP time when we received the last report
2098 // This is the value that we read from the send report packet not when we
2099 // received it...
2100 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
2101 pos += 4;
2102
2103 // Delay since last received report,time since we received the report
2104 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2105 received->delaySinceLastSR);
2106 pos += 4;
2107 }
2108 if ((pos + _reportBlocks.size() * 24) >= IP_PACKET_SIZE) {
2109 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
2110 "%s invalid argument", __FUNCTION__);
2111 return -1;
2112 }
2113 std::map<WebRtc_UWord32, RTCPReportBlock*>::iterator it =
2114 _reportBlocks.begin();
2115
2116 for (; it != _reportBlocks.end(); it++) {
2117 // we can have multiple report block in a conference
2118 WebRtc_UWord32 remoteSSRC = it->first;
2119 RTCPReportBlock* reportBlock = it->second;
2120 if (reportBlock) {
2121 // Remote SSRC
2122 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
2123 pos += 4;
2124
2125 // fraction lost
2126 rtcpbuffer[pos++] = reportBlock->fractionLost;
2127
2128 // cumulative loss
2129 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
2130 reportBlock->cumulativeLost);
2131 pos += 3;
2132
2133 // extended highest seq_no, contain the highest sequence number received
2134 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2135 reportBlock->extendedHighSeqNum);
2136 pos += 4;
2137
2138 //Jitter
2139 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2140 reportBlock->jitter);
2141 pos += 4;
2142
2143 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2144 reportBlock->lastSR);
2145 pos += 4;
2146
2147 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
2148 reportBlock->delaySinceLastSR);
2149 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002150 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002151 }
2152 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00002153}
2154
2155// no callbacks allowed inside this function
2156WebRtc_Word32
2157RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
2158 const WebRtc_UWord32 maxBitrateKbit)
2159{
2160 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2161
2162 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2163 {
2164 _sendTMMBN = true;
2165 return 0;
2166 }
2167 return -1;
2168}
2169
niklase@google.com470e71d2011-07-07 08:21:25 +00002170RateControlRegion
2171RTCPSender::UpdateOverUseState(const RateControlInput& rateControlInput, bool& firstOverUse)
2172{
2173 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00002174 return _remoteRateControl.Update(rateControlInput, firstOverUse,
2175 _clock.GetTimeInMS());
niklase@google.com470e71d2011-07-07 08:21:25 +00002176}
2177} // namespace webrtc