blob: 750dd65579cbe352d23cad7d689d9f3a445431a3 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
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"
12#include "rtcp_utility.h"
13
14#include <string.h> // memcpy
15#include <cassert> // assert
16#include <cstdlib> // rand
17
18#include "trace.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000019#include "common_types.h"
20#include "critical_section_wrapper.h"
21
pwestin@webrtc.org741da942011-09-20 13:52:04 +000022#include "rtp_rtcp_impl.h"
23
niklase@google.com470e71d2011-07-07 08:21:25 +000024namespace webrtc {
25RTCPSender::RTCPSender(const WebRtc_Word32 id,
26 const bool audio,
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000027 RtpRtcpClock* clock,
pwestin@webrtc.org741da942011-09-20 13:52:04 +000028 ModuleRtpRtcpImpl* owner) :
niklase@google.com470e71d2011-07-07 08:21:25 +000029 _id(id),
30 _audio(audio),
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000031 _clock(*clock),
niklase@google.com470e71d2011-07-07 08:21:25 +000032 _method(kRtcpOff),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000033 _rtpRtcp(*owner),
henrike@webrtc.org65573f22011-12-13 19:17:27 +000034 _criticalSectionTransport(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000035 _cbTransport(NULL),
36
henrike@webrtc.org65573f22011-12-13 19:17:27 +000037 _criticalSectionRTCPSender(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000038 _usingNack(false),
39 _sending(false),
40 _sendTMMBN(false),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000041 _REMB(false),
42 _sendREMB(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000043 _TMMBR(false),
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +000044 _IJ(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000045 _nextTimeToSendRTCP(0),
46 _SSRC(0),
47 _remoteSSRC(0),
48 _CNAME(),
49 _reportBlocks(),
50 _csrcCNAMEs(),
51
52 _cameraDelayMS(0),
53
54 _lastSendReport(),
55 _lastRTCPTime(),
56
57 _CSRCs(0),
58 _CSRC(),
59 _includeCSRCs(true),
60
61 _sequenceNumberFIR(0),
62 _lastTimeFIR(0),
63
pwestin@webrtc.org741da942011-09-20 13:52:04 +000064 _lengthRembSSRC(0),
65 _sizeRembSSRC(0),
66 _rembSSRC(NULL),
67 _rembBitrate(0),
mflodman@webrtc.org80d60422012-01-12 14:28:53 +000068 _bitrate_observer(NULL),
pwestin@webrtc.org741da942011-09-20 13:52:04 +000069
niklase@google.com470e71d2011-07-07 08:21:25 +000070 _tmmbrHelp(audio),
71 _tmmbr_Send(0),
72 _packetOH_Send(0),
73 _remoteRateControl(),
74
75 _appSend(false),
76 _appSubType(0),
77 _appName(),
78 _appData(NULL),
79 _appLength(0),
80 _xrSendVoIPMetric(false),
81 _xrVoIPMetric()
82{
83 memset(_CNAME, 0, sizeof(_CNAME));
84 memset(_lastSendReport, 0, sizeof(_lastSendReport));
85 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
86
87 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
88}
89
90RTCPSender::~RTCPSender()
91{
pwestin@webrtc.org741da942011-09-20 13:52:04 +000092 delete [] _rembSSRC;
93 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +000094
95 MapItem* item = _reportBlocks.First();
96 while(item)
97 {
98 RTCPReportBlock* ptr = (RTCPReportBlock*)(item->GetItem());
99 if(ptr)
100 {
101 delete ptr;
102 }
103 _reportBlocks.Erase(item);
104 item = _reportBlocks.First();
105 }
106 item = _csrcCNAMEs.First();
107 while(item)
108 {
109 RTCPUtility::RTCPCnameInformation* ptr = (RTCPUtility::RTCPCnameInformation*)(item->GetItem());
110 if(ptr)
111 {
112 delete ptr;
113 }
114 _csrcCNAMEs.Erase(item);
115 item = _csrcCNAMEs.First();
116 }
henrike@webrtc.org65573f22011-12-13 19:17:27 +0000117 delete _criticalSectionTransport;
118 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000119
120 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
121}
122
123WebRtc_Word32
124RTCPSender::Init()
125{
126 CriticalSectionScoped lock(_criticalSectionRTCPSender);
127
128 _method = kRtcpOff;
129 _cbTransport = NULL;
130 _usingNack = false;
131 _sending = false;
132 _sendTMMBN = false;
133 _TMMBR = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000134 _IJ = false;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000135 _REMB = false;
136 _sendREMB = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000137 _SSRC = 0;
138 _remoteSSRC = 0;
139 _cameraDelayMS = 0;
140 _sequenceNumberFIR = 0;
141 _tmmbr_Send = 0;
142 _packetOH_Send = 0;
143 _remoteRateControl.Reset();
144 _nextTimeToSendRTCP = 0;
145 _CSRCs = 0;
146 _appSend = false;
147 _appSubType = 0;
148
149 if(_appData)
150 {
151 delete [] _appData;
152 _appData = NULL;
153 }
154 _appLength = 0;
155
156 _xrSendVoIPMetric = false;
157
158 memset(&_xrVoIPMetric, 0, sizeof(_xrVoIPMetric));
159 memset(_CNAME, 0, sizeof(_CNAME));
160 memset(_lastSendReport, 0, sizeof(_lastSendReport));
161 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
162 return 0;
163}
164
165void
166RTCPSender::ChangeUniqueId(const WebRtc_Word32 id)
167{
168 _id = id;
169}
170
171WebRtc_Word32
172RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
173{
174 CriticalSectionScoped lock(_criticalSectionTransport);
175 _cbTransport = outgoingTransport;
176 return 0;
177}
178
179RTCPMethod
180RTCPSender::Status() const
181{
182 CriticalSectionScoped lock(_criticalSectionRTCPSender);
183 return _method;
184}
185
186WebRtc_Word32
187RTCPSender::SetRTCPStatus(const RTCPMethod method)
188{
189 CriticalSectionScoped lock(_criticalSectionRTCPSender);
190 if(method != kRtcpOff)
191 {
192 if(_audio)
193 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000194 _nextTimeToSendRTCP = _clock.GetTimeInMS() + (RTCP_INTERVAL_AUDIO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000195 } else
196 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000197 _nextTimeToSendRTCP = _clock.GetTimeInMS() + (RTCP_INTERVAL_VIDEO_MS/2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000198 }
199 }
200 _method = method;
201 return 0;
202}
203
204bool
205RTCPSender::Sending() const
206{
207 CriticalSectionScoped lock(_criticalSectionRTCPSender);
208 return _sending;
209}
210
211WebRtc_Word32
212RTCPSender::SetSendingStatus(const bool sending)
213{
214 bool sendRTCPBye = false;
215 {
216 CriticalSectionScoped lock(_criticalSectionRTCPSender);
217
218 if(_method != kRtcpOff)
219 {
220 if(sending == false && _sending == true)
221 {
222 // Trigger RTCP bye
223 sendRTCPBye = true;
224 }
225 }
226 _sending = sending;
227 }
228 if(sendRTCPBye)
229 {
230 return SendRTCP(kRtcpBye);
231 }
232 return 0;
233}
234
235bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000236RTCPSender::REMB() const
237{
238 CriticalSectionScoped lock(_criticalSectionRTCPSender);
239 return _REMB;
240}
241
242WebRtc_Word32
243RTCPSender::SetREMBStatus(const bool enable)
244{
245 CriticalSectionScoped lock(_criticalSectionRTCPSender);
246 _REMB = enable;
247 return 0;
248}
249
250WebRtc_Word32
251RTCPSender::SetREMBData(const WebRtc_UWord32 bitrate,
252 const WebRtc_UWord8 numberOfSSRC,
253 const WebRtc_UWord32* SSRC)
254{
255 CriticalSectionScoped lock(_criticalSectionRTCPSender);
256 _rembBitrate = bitrate;
257
258 if(_sizeRembSSRC < numberOfSSRC)
259 {
260 delete [] _rembSSRC;
261 _rembSSRC = new WebRtc_UWord32[numberOfSSRC];
262 _sizeRembSSRC = numberOfSSRC;
263 }
264
265 _lengthRembSSRC = numberOfSSRC;
266 for (int i = 0; i < numberOfSSRC; i++)
267 {
268 _rembSSRC[i] = SSRC[i];
269 }
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000270 _sendREMB = true;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000271 return 0;
272}
273
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000274bool RTCPSender::SetRemoteBitrateObserver(RtpRemoteBitrateObserver* observer) {
275 CriticalSectionScoped lock(_criticalSectionRTCPSender);
276 if (observer && _bitrate_observer) {
277 return false;
278 }
279 _bitrate_observer = observer;
280 return true;
281}
282
283void RTCPSender::UpdateRemoteBitrateEstimate(unsigned int target_bitrate) {
284 CriticalSectionScoped lock(_criticalSectionRTCPSender);
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000285 if (_bitrate_observer) {
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +0000286 _bitrate_observer->OnReceiveBitrateChanged(_remoteSSRC, target_bitrate);
287 }
288}
289
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000290bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000291RTCPSender::TMMBR() const
292{
293 CriticalSectionScoped lock(_criticalSectionRTCPSender);
294 return _TMMBR;
295}
296
297WebRtc_Word32
298RTCPSender::SetTMMBRStatus(const bool enable)
299{
300 CriticalSectionScoped lock(_criticalSectionRTCPSender);
301 _TMMBR = enable;
302 return 0;
303}
304
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000305bool
306RTCPSender::IJ() const
307{
308 CriticalSectionScoped lock(_criticalSectionRTCPSender);
309 return _IJ;
310}
311
312WebRtc_Word32
313RTCPSender::SetIJStatus(const bool enable)
314{
315 CriticalSectionScoped lock(_criticalSectionRTCPSender);
316 _IJ = enable;
317 return 0;
318}
319
niklase@google.com470e71d2011-07-07 08:21:25 +0000320void
321RTCPSender::SetSSRC( const WebRtc_UWord32 ssrc)
322{
323 CriticalSectionScoped lock(_criticalSectionRTCPSender);
324
325 if(_SSRC != 0)
326 {
327 // not first SetSSRC, probably due to a collision
328 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000329 // make sure that we send a RTP packet
330 _nextTimeToSendRTCP = _clock.GetTimeInMS() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000331 }
332 _SSRC = ssrc;
333}
334
335WebRtc_Word32
336RTCPSender::SetRemoteSSRC( const WebRtc_UWord32 ssrc)
337{
338 CriticalSectionScoped lock(_criticalSectionRTCPSender);
339 _remoteSSRC = ssrc;
340 _remoteRateControl.Reset();
341 return 0;
342}
343
344WebRtc_Word32
345RTCPSender::SetCameraDelay(const WebRtc_Word32 delayMS)
346{
347 CriticalSectionScoped lock(_criticalSectionRTCPSender);
348 if(delayMS > 1000 || delayMS < -1000)
349 {
350 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, delay can't be larger than 1 sec", __FUNCTION__);
351 return -1;
352 }
353 _cameraDelayMS = delayMS;
354 return 0;
355}
356
357WebRtc_Word32
358RTCPSender::CNAME(WebRtc_Word8 cName[RTCP_CNAME_SIZE])
359{
360 if(cName == NULL)
361 {
362 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
363 return -1;
364 }
365 CriticalSectionScoped lock(_criticalSectionRTCPSender);
366 memcpy(cName, _CNAME, RTCP_CNAME_SIZE);
367 return 0;
368}
369
370WebRtc_Word32
371RTCPSender::SetCNAME(const WebRtc_Word8 cName[RTCP_CNAME_SIZE])
372{
373 if(cName == NULL)
374 {
375 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
376 return -1;
377 }
378 WebRtc_Word32 length = (WebRtc_Word32)strlen(cName);
379 if(length > RTCP_CNAME_SIZE)
380 {
381 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, too long cName", __FUNCTION__);
382 return -1;
383 }
384 CriticalSectionScoped lock(_criticalSectionRTCPSender);
385
386 memcpy(_CNAME, cName, length+1);
387 return 0;
388}
389
390WebRtc_Word32
391RTCPSender::AddMixedCNAME(const WebRtc_UWord32 SSRC,
392 const WebRtc_Word8 cName[RTCP_CNAME_SIZE])
393{
394 if(cName == NULL)
395 {
396 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
397 return -1;
398 }
399 WebRtc_Word32 length = (WebRtc_Word32)strlen(cName);
400 if(length > RTCP_CNAME_SIZE)
401 {
402 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument, too long cName", __FUNCTION__);
403 return -1;
404 }
405
406 CriticalSectionScoped lock(_criticalSectionRTCPSender);
407 if(_csrcCNAMEs.Size() == kRtpCsrcSize)
408 {
409 return -1;
410 }
411 RTCPUtility::RTCPCnameInformation* ptr= new RTCPUtility::RTCPCnameInformation();
412
413 memcpy(ptr->name, cName, length+1);
414 ptr->length = (WebRtc_UWord8)length;
415 _csrcCNAMEs.Insert(SSRC, ptr);
416 return 0;
417}
418
419WebRtc_Word32
420RTCPSender::RemoveMixedCNAME(const WebRtc_UWord32 SSRC)
421{
422 CriticalSectionScoped lock(_criticalSectionRTCPSender);
423 MapItem* item= _csrcCNAMEs.Find(SSRC);
424 if(item)
425 {
426 RTCPUtility::RTCPCnameInformation* ptr= (RTCPUtility::RTCPCnameInformation*)(item->GetItem());
427 if(ptr)
428 {
429 delete ptr;
430 }
431 _csrcCNAMEs.Erase(item);
432 return 0;
433 }
434 return -1;
435}
436
437bool
438RTCPSender::TimeToSendRTCPReport(const bool sendKeyframeBeforeRTP) const
439{
440/*
441 For audio we use a fix 5 sec interval
442
443 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
444 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but that should be extreamly rare
445
446
447From RFC 3550
448
449 MAX RTCP BW is 5% if the session BW
450 A send report is approximately 65 bytes inc CNAME
451 A report report is approximately 28 bytes
452
453 The RECOMMENDED value for the reduced minimum in seconds is 360
454 divided by the session bandwidth in kilobits/second. This minimum
455 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
456
457 If the participant has not yet sent an RTCP packet (the variable
458 initial is true), the constant Tmin is set to 2.5 seconds, else it
459 is set to 5 seconds.
460
461 The interval between RTCP packets is varied randomly over the
462 range [0.5,1.5] times the calculated interval to avoid unintended
463 synchronization of all participants
464
465 if we send
466 If the participant is a sender (we_sent true), the constant C is
467 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
468 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
469 number of senders.
470
471 if we receive only
472 If we_sent is not true, the constant C is set
473 to the average RTCP packet size divided by 75% of the RTCP
474 bandwidth. The constant n is set to the number of receivers
475 (members - senders). If the number of senders is greater than
476 25%, senders and receivers are treated together.
477
478 reconsideration NOT required for peer-to-peer
479 "timer reconsideration" is
480 employed. This algorithm implements a simple back-off mechanism
481 which causes users to hold back RTCP packet transmission if the
482 group sizes are increasing.
483
484 n = number of members
485 C = avg_size/(rtcpBW/4)
486
487 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
488
489 4. The calculated interval T is set to a number uniformly distributed
490 between 0.5 and 1.5 times the deterministic calculated interval.
491
492 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
493 for the fact that the timer reconsideration algorithm converges to
494 a value of the RTCP bandwidth below the intended average
495*/
496
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000497 WebRtc_UWord32 now = _clock.GetTimeInMS();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000498
499 CriticalSectionScoped lock(_criticalSectionRTCPSender);
500
niklase@google.com470e71d2011-07-07 08:21:25 +0000501 if(_method == kRtcpOff)
502 {
503 return false;
504 }
505
niklase@google.com470e71d2011-07-07 08:21:25 +0000506 if(!_audio && sendKeyframeBeforeRTP)
507 {
508 // for video key-frames we want to send the RTCP before the large key-frame
509 // if we have a 100 ms margin
510 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
511 }
512
513 if(now > _nextTimeToSendRTCP)
514 {
515 return true;
516
517 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
518 {
519 // wrap
520 return true;
521 }
522 return false;
523}
524
525WebRtc_UWord32
526RTCPSender::LastSendReport( WebRtc_UWord32& lastRTCPTime)
527{
528 CriticalSectionScoped lock(_criticalSectionRTCPSender);
529
530 lastRTCPTime = _lastRTCPTime[0];
531 return _lastSendReport[0];
532}
533
534WebRtc_UWord32
535RTCPSender::SendTimeOfSendReport(const WebRtc_UWord32 sendReport)
536{
537 CriticalSectionScoped lock(_criticalSectionRTCPSender);
538
539 // This is only saved when we are the sender
540 if((_lastSendReport[0] == 0) || (sendReport == 0))
541 {
542 return 0; // will be ignored
543 } else
544 {
545 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
546 {
547 if( _lastSendReport[i] == sendReport)
548 {
549 return _lastRTCPTime[i];
550 }
551 }
552 }
553 return 0;
554}
555
556WebRtc_Word32
557RTCPSender::AddReportBlock(const WebRtc_UWord32 SSRC,
558 const RTCPReportBlock* reportBlock)
559{
560 if(reportBlock == NULL)
561 {
562 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
563 return -1;
564 }
565
566 CriticalSectionScoped lock(_criticalSectionRTCPSender);
567
568 if(_reportBlocks.Size() >= RTCP_MAX_REPORT_BLOCKS)
569 {
570 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
571 return -1;
572 }
573 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
574 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
575 _reportBlocks.Insert(SSRC, copyReportBlock);
576 return 0;
577}
578
579WebRtc_Word32
580RTCPSender::RemoveReportBlock(const WebRtc_UWord32 SSRC)
581{
582 CriticalSectionScoped lock(_criticalSectionRTCPSender);
583
584 MapItem* item= _reportBlocks.Find(SSRC);
585 if(item)
586 {
587 RTCPReportBlock* ptr= (RTCPReportBlock*)(item->GetItem());
588 if(ptr)
589 {
590 delete ptr;
591 }
592 _reportBlocks.Erase(item);
593 return 0;
594 }
595 return -1;
596}
597
598WebRtc_Word32
599RTCPSender::BuildSR(WebRtc_UWord8* rtcpbuffer,
600 WebRtc_UWord32& pos,
601 const WebRtc_UWord32 NTPsec,
602 const WebRtc_UWord32 NTPfrac,
603 const RTCPReportBlock* received)
604{
605 // sanity
606 if(pos + 52 >= IP_PACKET_SIZE)
607 {
608 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
609 return -2;
610 }
611 WebRtc_UWord32 RTPtime;
612 WebRtc_UWord32 BackTimedNTPsec;
613 WebRtc_UWord32 BackTimedNTPfrac;
614
615 WebRtc_UWord32 posNumberOfReportBlocks = pos;
616 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
617
618 // Sender report
619 rtcpbuffer[pos++]=(WebRtc_UWord8)200;
620
621 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
622 {
623 // shift old
624 _lastSendReport[i+1] = _lastSendReport[i];
625 _lastRTCPTime[i+1] =_lastRTCPTime[i];
626 }
627
628 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac); // before video cam compensation
629
630 if(_cameraDelayMS >= 0)
631 {
632 // fraction of a second as an unsigned word32 4.294 967 296E9
633 WebRtc_UWord32 cameraDelayFixFrac = (WebRtc_UWord32)_cameraDelayMS* 4294967; // note camera delay can't be larger than +/-1000ms
634 if(NTPfrac > cameraDelayFixFrac)
635 {
636 // no problem just reduce the fraction part
637 BackTimedNTPfrac = NTPfrac - cameraDelayFixFrac;
638 BackTimedNTPsec = NTPsec;
639 } else
640 {
641 // we need to reduce the sec and add that sec to the frac
642 BackTimedNTPsec = NTPsec - 1;
643 BackTimedNTPfrac = 0xffffffff - (cameraDelayFixFrac - NTPfrac);
644 }
645 } else
646 {
647 // fraction of a second as an unsigned word32 4.294 967 296E9
648 WebRtc_UWord32 cameraDelayFixFrac = (WebRtc_UWord32)(-_cameraDelayMS)* 4294967; // note camera delay can't be larger than +/-1000ms
649 if(NTPfrac > 0xffffffff - cameraDelayFixFrac)
650 {
651 // we need to add the sec and add that sec to the frac
652 BackTimedNTPsec = NTPsec + 1;
653 BackTimedNTPfrac = cameraDelayFixFrac + NTPfrac; // this will wrap but that is ok
654 } else
655 {
656 // no problem just add the fraction part
657 BackTimedNTPsec = NTPsec;
658 BackTimedNTPfrac = NTPfrac + cameraDelayFixFrac;
659 }
660 }
661 _lastSendReport[0] = (BackTimedNTPsec <<16) + (BackTimedNTPfrac >> 16);
662
663 // RTP timestamp
664 // This should have a ramdom start value added
665 // RTP is counted from NTP not the acctual RTP
666 // This reflects the perfect RTP time
667 // we solve this by initiating RTP to our NTP :)
668
669 WebRtc_UWord32 freqHz = 90000; // For video
670 if(_audio)
671 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000672 freqHz = _rtpRtcp.CurrentSendFrequencyHz();
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000673 RTPtime = ModuleRTPUtility::GetCurrentRTP(&_clock, freqHz);
niklase@google.com470e71d2011-07-07 08:21:25 +0000674 }
675 else // video
676 {
677 // used to be (WebRtc_UWord32)(((float)BackTimedNTPfrac/(float)FRAC)* 90000)
678 WebRtc_UWord32 tmp = 9*(BackTimedNTPfrac/429496);
679 RTPtime = BackTimedNTPsec*freqHz + tmp;
680 }
681
682
683
684
685 // Add sender data
686 // Save for our length field
687 pos++;
688 pos++;
689
690 // Add our own SSRC
691 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
692 pos += 4;
693 // NTP
694 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, BackTimedNTPsec);
695 pos += 4;
696 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, BackTimedNTPfrac);
697 pos += 4;
698 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, RTPtime);
699 pos += 4;
700
701 //sender's packet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000702 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000703 pos += 4;
704
705 //sender's octet count
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000706 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
niklase@google.com470e71d2011-07-07 08:21:25 +0000707 pos += 4;
708
709 WebRtc_UWord8 numberOfReportBlocks = 0;
710 WebRtc_Word32 retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
711 if(retVal < 0)
712 {
713 //
714 return retVal ;
715 }
716 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
717
718 WebRtc_UWord16 len = WebRtc_UWord16((pos/4) -1);
719 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
720 return 0;
721}
722
723
724WebRtc_Word32
725RTCPSender::BuildSDEC(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
726{
727 WebRtc_UWord32 lengthCname =(WebRtc_UWord32)strlen((char*)_CNAME);
728
729 // sanity max is 255
730 if(lengthCname > RTCP_CNAME_SIZE)
731 {
732 lengthCname = RTCP_CNAME_SIZE;
733 }
734 // sanity
735 if(pos + 12+ lengthCname >= IP_PACKET_SIZE)
736 {
737 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
738 return -2;
739 }
740 // SDEC Source Description
741
742 // We always need to add SDES CNAME
743 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1 + _csrcCNAMEs.Size(); // source counts
744 rtcpbuffer[pos++]=(WebRtc_UWord8)202;
745
746 // handle SDES length later on
747 WebRtc_UWord32 SDESLengthPos = pos;
748 pos++;
749 pos++;
750
751 // Add our own SSRC
752 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
753 pos += 4;
754
755 // CNAME = 1
756 rtcpbuffer[pos++]=(WebRtc_UWord8)1;
757
758 //
759 rtcpbuffer[pos++]=(WebRtc_UWord8)lengthCname;
760
761 WebRtc_UWord16 SDESLength = 10;
762
763 memcpy(&rtcpbuffer[pos],_CNAME,lengthCname);
764 pos += lengthCname;
765 SDESLength += (WebRtc_UWord16)lengthCname;
766
767 WebRtc_UWord16 padding =0;
768
769 // We must have a zero field even if we have an even multiple of 4 bytes
770 if((pos % 4) ==0)
771 {
772 padding++;
773 rtcpbuffer[pos++]=0;
774 }
775 while((pos % 4) !=0)
776 {
777 padding++;
778 rtcpbuffer[pos++]=0;
779 }
780 SDESLength += padding;
781
782 MapItem* item = _csrcCNAMEs.First();
783
784 for(int i = 0; item && i < _csrcCNAMEs.Size(); i++)
785 {
786 RTCPUtility::RTCPCnameInformation* cname = (RTCPUtility::RTCPCnameInformation*)(item->GetItem());
787 WebRtc_UWord32 SSRC = item->GetUnsignedId();
788
789 // Add SSRC
790 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, SSRC);
791 pos += 4;
792
793 // CNAME = 1
794 rtcpbuffer[pos++]=(WebRtc_UWord8)1;
795
796 rtcpbuffer[pos++]= cname->length;
797
798 SDESLength += 6;
799
800 memcpy(&rtcpbuffer[pos],cname->name, cname->length);
801 pos += cname->length;
802 SDESLength += cname->length;
803
804 WebRtc_UWord16 padding =0;
805
806 // We must have a zero field even if we have an even multiple of 4 bytes
807 if((pos % 4) ==0)
808 {
809 padding++;
810 rtcpbuffer[pos++]=0;
811 }
812 while((pos % 4) !=0)
813 {
814 padding++;
815 rtcpbuffer[pos++]=0;
816 }
817 SDESLength += padding;
818
819 item = _csrcCNAMEs.Next(item);
820 }
821 WebRtc_UWord16 length = SDESLength;
822 length= (length/4) - 1; // in 32-bit words minus one and we dont count the header
823
824 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+SDESLengthPos, length);
825 return 0;
826}
827
828WebRtc_Word32
829RTCPSender::BuildRR(WebRtc_UWord8* rtcpbuffer,
830 WebRtc_UWord32& pos,
831 const WebRtc_UWord32 NTPsec,
832 const WebRtc_UWord32 NTPfrac,
833 const RTCPReportBlock* received)
834{
835 // sanity one block
836 if(pos + 32 >= IP_PACKET_SIZE)
837 {
838 return -2;
839 }
840 WebRtc_UWord32 posNumberOfReportBlocks = pos;
841
842 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
843 rtcpbuffer[pos++]=(WebRtc_UWord8)201;
844
845 // Save for our length field
846 pos++;
847 pos++;
848
849 // Add our own SSRC
850 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
851 pos += 4;
852
853 WebRtc_UWord8 numberOfReportBlocks = 0;
854 WebRtc_Word32 retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
855 if(retVal < 0)
856 {
857 return retVal;
858 }
859 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
860
861 WebRtc_UWord16 len = WebRtc_UWord16((pos)/4 -1);
862 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+2, len);
863 return 0;
864}
865
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000866// From RFC 5450: Transmission Time Offsets in RTP Streams.
867// 0 1 2 3
868// 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
869// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
870// hdr |V=2|P| RC | PT=IJ=195 | length |
871// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
872// | inter-arrival jitter |
873// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
874// . .
875// . .
876// . .
877// | inter-arrival jitter |
878// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
879//
880// If present, this RTCP packet must be placed after a receiver report
881// (inside a compound RTCP packet), and MUST have the same value for RC
882// (reception report count) as the receiver report.
883
884WebRtc_Word32
885RTCPSender::BuildExtendedJitterReport(
886 WebRtc_UWord8* rtcpbuffer,
887 WebRtc_UWord32& pos,
888 const WebRtc_UWord32 jitterTransmissionTimeOffset)
889{
890 if (_reportBlocks.Size() > 0)
891 {
892 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
893 return 0;
894 }
895
896 // sanity
897 if(pos + 8 >= IP_PACKET_SIZE)
898 {
899 return -2;
900 }
901 // add picture loss indicator
902 WebRtc_UWord8 RC = 1;
903 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + RC;
904 rtcpbuffer[pos++]=(WebRtc_UWord8)195;
905
906 // Used fixed length of 2
907 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
908 rtcpbuffer[pos++]=(WebRtc_UWord8)(1);
909
910 // Add inter-arrival jitter
911 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
912 jitterTransmissionTimeOffset);
913 pos += 4;
914 return 0;
915}
916
niklase@google.com470e71d2011-07-07 08:21:25 +0000917WebRtc_Word32
918RTCPSender::BuildPLI(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
919{
920 // sanity
921 if(pos + 12 >= IP_PACKET_SIZE)
922 {
923 return -2;
924 }
925 // add picture loss indicator
926 WebRtc_UWord8 FMT = 1;
927 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
928 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
929
930 //Used fixed length of 2
931 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
932 rtcpbuffer[pos++]=(WebRtc_UWord8)(2);
933
934 // Add our own SSRC
935 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
936 pos += 4;
937
938 // Add the remote SSRC
939 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
940 pos += 4;
941 return 0;
942}
943
944WebRtc_Word32
945RTCPSender::BuildFIR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos, const WebRtc_UWord32 RTT)
946{
947 bool firRepeat = false;
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000948 WebRtc_UWord32 diff = _clock.GetTimeInMS() - _lastTimeFIR;
niklase@google.com470e71d2011-07-07 08:21:25 +0000949 if(diff < RTT + 3) // 3 is processing jitter
950 {
951 // we have recently sent a FIR
952 // don't send another
953 return 0;
954
955 } else
956 {
957 if(diff < (RTT*2 + RTCP_MIN_FRAME_LENGTH_MS))
958 {
959 // send a FIR_REPEAT instead of a FIR
960 firRepeat = true;
961 }
962 }
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000963 _lastTimeFIR = _clock.GetTimeInMS();
niklase@google.com470e71d2011-07-07 08:21:25 +0000964 if(!firRepeat)
965 {
966 _sequenceNumberFIR++; // do not increase if repetition
967 }
968
969 // sanity
970 if(pos + 20 >= IP_PACKET_SIZE)
971 {
972 return -2;
973 }
974
975 // add full intra request indicator
976 WebRtc_UWord8 FMT = 4;
977 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
978 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
979
980 //Length of 4
981 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
982 rtcpbuffer[pos++]=(WebRtc_UWord8)(4);
983
984 // Add our own SSRC
985 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
986 pos += 4;
987
988 // RFC 5104 4.3.1.2. Semantics
989
990 // SSRC of media source
991 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
992 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
993 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
994 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
995
996 // Additional Feedback Control Information (FCI)
997 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
998 pos += 4;
999
1000 rtcpbuffer[pos++]=(WebRtc_UWord8)(_sequenceNumberFIR);
1001 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1002 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1003 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1004 return 0;
1005}
1006
1007/*
1008 0 1 2 3
1009 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
1010 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1011 | First | Number | PictureID |
1012 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1013*/
1014WebRtc_Word32
1015RTCPSender::BuildSLI(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos, const WebRtc_UWord8 pictureID)
1016{
1017 // sanity
1018 if(pos + 16 >= IP_PACKET_SIZE)
1019 {
1020 return -2;
1021 }
1022 // add slice loss indicator
1023 WebRtc_UWord8 FMT = 2;
1024 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1025 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
1026
1027 //Used fixed length of 3
1028 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1029 rtcpbuffer[pos++]=(WebRtc_UWord8)(3);
1030
1031 // Add our own SSRC
1032 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1033 pos += 4;
1034
1035 // Add the remote SSRC
1036 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1037 pos += 4;
1038
1039 // Add first, number & picture ID 6 bits
1040 // first = 0, 13 - bits
1041 // number = 0x1fff, 13 - bits only ones for now
1042 WebRtc_UWord32 sliField = (0x1fff << 6)+ (0x3f & pictureID);
1043 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, sliField);
1044 pos += 4;
1045 return 0;
1046}
1047
1048/*
1049 0 1 2 3
1050 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
1051 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1052 | PB |0| Payload Type| Native RPSI bit string |
1053 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1054 | defined per codec ... | Padding (0) |
1055 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1056*/
1057/*
1058* Note: not generic made for VP8
1059*/
1060WebRtc_Word32
1061RTCPSender::BuildRPSI(WebRtc_UWord8* rtcpbuffer,
1062 WebRtc_UWord32& pos,
1063 const WebRtc_UWord64 pictureID,
1064 const WebRtc_UWord8 payloadType)
1065{
1066 // sanity
1067 if(pos + 24 >= IP_PACKET_SIZE)
1068 {
1069 return -2;
1070 }
1071 // add Reference Picture Selection Indication
1072 WebRtc_UWord8 FMT = 3;
1073 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1074 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
1075
1076 // calc length
1077 WebRtc_UWord32 bitsRequired = 7;
1078 WebRtc_UWord8 bytesRequired = 1;
1079 while((pictureID>>bitsRequired) > 0)
1080 {
1081 bitsRequired += 7;
1082 bytesRequired++;
1083 }
1084
1085 WebRtc_UWord8 size = 3;
1086 if(bytesRequired > 6)
1087 {
1088 size = 5;
1089 } else if(bytesRequired > 2)
1090 {
1091 size = 4;
1092 }
1093 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1094 rtcpbuffer[pos++]=size;
1095
1096 // Add our own SSRC
1097 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1098 pos += 4;
1099
1100 // Add the remote SSRC
1101 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1102 pos += 4;
1103
1104 // calc padding length
1105 WebRtc_UWord8 paddingBytes = 4-((2+bytesRequired)%4);
1106 if(paddingBytes == 4)
1107 {
1108 paddingBytes = 0;
1109 }
1110 // add padding length in bits
1111 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
1112 pos++;
1113
1114 // add payload type
1115 rtcpbuffer[pos] = payloadType;
1116 pos++;
1117
1118 // add picture ID
1119 for(int i = bytesRequired-1; i > 0; i--)
1120 {
1121 rtcpbuffer[pos] = 0x80 | WebRtc_UWord8(pictureID >> (i*7));
1122 pos++;
1123 }
1124 // add last byte of picture ID
1125 rtcpbuffer[pos] = WebRtc_UWord8(pictureID & 0x7f);
1126 pos++;
1127
1128 // add padding
1129 for(int j = 0; j <paddingBytes; j++)
1130 {
1131 rtcpbuffer[pos] = 0;
1132 pos++;
1133 }
1134 return 0;
1135}
1136
1137WebRtc_Word32
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001138RTCPSender::BuildREMB(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1139{
1140 // sanity
1141 if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
1142 {
1143 return -2;
1144 }
1145 // add application layer feedback
1146 WebRtc_UWord8 FMT = 15;
1147 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1148 rtcpbuffer[pos++]=(WebRtc_UWord8)206;
1149
1150 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1151 rtcpbuffer[pos++]=_lengthRembSSRC + 4;
1152
1153 // Add our own SSRC
1154 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1155 pos += 4;
1156
1157 // Remote SSRC must be 0
1158 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
1159 pos += 4;
1160
1161 rtcpbuffer[pos++]='R';
1162 rtcpbuffer[pos++]='E';
1163 rtcpbuffer[pos++]='M';
1164 rtcpbuffer[pos++]='B';
1165
1166 rtcpbuffer[pos++] = _lengthRembSSRC;
1167 // 6 bit Exp
1168 // 18 bit mantissa
1169 WebRtc_UWord8 brExp = 0;
1170 for(WebRtc_UWord32 i=0; i<64; i++)
1171 {
1172 if(_rembBitrate <= ((WebRtc_UWord32)262143 << i))
1173 {
1174 brExp = i;
1175 break;
1176 }
1177 }
1178 const WebRtc_UWord32 brMantissa = (_rembBitrate >> brExp);
1179 rtcpbuffer[pos++]=(WebRtc_UWord8)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1180 rtcpbuffer[pos++]=(WebRtc_UWord8)(brMantissa >> 8);
1181 rtcpbuffer[pos++]=(WebRtc_UWord8)(brMantissa);
1182
1183 for (int i = 0; i < _lengthRembSSRC; i++)
1184 {
1185 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
1186 pos += 4;
1187 }
1188 return 0;
1189}
1190
1191WebRtc_UWord32
1192RTCPSender::CalculateNewTargetBitrate(WebRtc_UWord32 RTT)
1193{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001194 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001195 WebRtc_UWord32 target_bitrate =
1196 _remoteRateControl.TargetBitRate(RTT, _clock.GetTimeInMS());
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001197 _tmmbr_Send = target_bitrate / 1000;
1198 return target_bitrate;
1199}
1200
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001201bool
1202RTCPSender::ValidBitrateEstimate() {
1203 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1204 return _remoteRateControl.ValidEstimate();
1205}
1206
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001207WebRtc_Word32
1208RTCPSender::BuildTMMBR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001209{
1210 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1211 // If the sender is an owner of the TMMBN -> send TMMBR
1212 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1213
niklase@google.com470e71d2011-07-07 08:21:25 +00001214 // get current bounding set from RTCP receiver
1215 bool tmmbrOwner = false;
1216 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet(); // store in candidateSet, allocates one extra slot
1217
1218 // holding _criticalSectionRTCPSender while calling RTCPreceiver which will accuire _criticalSectionRTCPReceiver
1219 // is a potental deadlock but since RTCPreceiver is not doing the revese we should be fine
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001220 WebRtc_Word32 lengthOfBoundingSet = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001221
1222 if(lengthOfBoundingSet > 0)
1223 {
1224 for (WebRtc_Word32 i = 0; i < lengthOfBoundingSet; i++)
1225 {
1226 if( candidateSet->ptrTmmbrSet[i] == _tmmbr_Send &&
1227 candidateSet->ptrPacketOHSet[i] == _packetOH_Send)
1228 {
1229 // do not send the same tuple
1230 return 0;
1231 }
1232 }
1233 if(!tmmbrOwner)
1234 {
1235 // use received bounding set as candidate set
1236 // add current tuple
1237 candidateSet->ptrTmmbrSet[lengthOfBoundingSet] = _tmmbr_Send;
1238 candidateSet->ptrPacketOHSet[lengthOfBoundingSet] = _packetOH_Send;
1239 candidateSet->ptrSsrcSet[lengthOfBoundingSet] = _SSRC;
1240 int numCandidates = lengthOfBoundingSet+ 1;
1241
1242 // find bounding set
1243 TMMBRSet* boundingSet = NULL;
1244 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1245 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1246 {
1247 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1248 }
1249 if(!tmmbrOwner)
1250 {
1251 // did not enter bounding set, no meaning to send this request
1252 return 0;
1253 }
1254 }
1255 }
1256
1257 if(_tmmbr_Send)
1258 {
1259 // sanity
1260 if(pos + 20 >= IP_PACKET_SIZE)
1261 {
1262 return -2;
1263 }
1264 // add TMMBR indicator
1265 WebRtc_UWord8 FMT = 3;
1266 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1267 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1268
1269 //Length of 4
1270 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1271 rtcpbuffer[pos++]=(WebRtc_UWord8)(4);
1272
1273 // Add our own SSRC
1274 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1275 pos += 4;
1276
1277 // RFC 5104 4.2.1.2. Semantics
1278
1279 // SSRC of media source
1280 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1281 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1282 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1283 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1284
1285 // Additional Feedback Control Information (FCI)
1286 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1287 pos += 4;
1288
1289 WebRtc_UWord32 bitRate = _tmmbr_Send*1000;
1290 WebRtc_UWord32 mmbrExp = 0;
1291 for(WebRtc_UWord32 i=0;i<64;i++)
1292 {
1293 if(bitRate <= ((WebRtc_UWord32)131071 << i))
1294 {
1295 mmbrExp = i;
1296 break;
1297 }
1298 }
1299 WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp);
1300
1301 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1302 rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);
1303 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1304 rtcpbuffer[pos++]=(WebRtc_UWord8)(_packetOH_Send);
1305 }
1306 return 0;
1307}
1308
1309WebRtc_Word32
1310RTCPSender::BuildTMMBN(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1311{
1312 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1313 if(boundingSet == NULL)
1314 {
1315 return -1;
1316 }
1317 // sanity
1318 if(pos + 12 + boundingSet->lengthOfSet*8 >= IP_PACKET_SIZE)
1319 {
1320 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1321 return -2;
1322 }
1323 WebRtc_UWord8 FMT = 4;
1324 // add TMMBN indicator
1325 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1326 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1327
1328 //Add length later
1329 int posLength = pos;
1330 pos++;
1331 pos++;
1332
1333 // Add our own SSRC
1334 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1335 pos += 4;
1336
1337 // RFC 5104 4.2.2.2. Semantics
1338
1339 // SSRC of media source
1340 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1341 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1342 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1343 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1344
1345 // Additional Feedback Control Information (FCI)
1346 int numBoundingSet = 0;
1347 for(WebRtc_UWord32 n=0; n< boundingSet->lengthOfSet; n++)
1348 {
1349 if (boundingSet->ptrTmmbrSet[n] > 0)
1350 {
1351 WebRtc_UWord32 tmmbrSSRC = boundingSet->ptrSsrcSet[n];
1352 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
1353 pos += 4;
1354
1355 WebRtc_UWord32 bitRate = boundingSet->ptrTmmbrSet[n] * 1000;
1356 WebRtc_UWord32 mmbrExp = 0;
1357 for(int i=0; i<64; i++)
1358 {
1359 if(bitRate <= ((WebRtc_UWord32)131071 << i))
1360 {
1361 mmbrExp = i;
1362 break;
1363 }
1364 }
1365 WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp);
1366 WebRtc_UWord32 measuredOH = boundingSet->ptrPacketOHSet[n];
1367
1368 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1369 rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);
1370 rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1371 rtcpbuffer[pos++]=(WebRtc_UWord8)(measuredOH);
1372 numBoundingSet++;
1373 }
1374 }
1375 WebRtc_UWord16 length= (WebRtc_UWord16)(2+2*numBoundingSet);
1376 rtcpbuffer[posLength++]=(WebRtc_UWord8)(length>>8);
1377 rtcpbuffer[posLength]=(WebRtc_UWord8)(length);
1378 return 0;
1379}
1380
1381WebRtc_Word32
1382RTCPSender::BuildAPP(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1383{
1384 // sanity
1385 if(_appData == NULL)
1386 {
1387 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
1388 return -1;
1389 }
1390 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1391 {
1392 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1393 return -2;
1394 }
1395 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + _appSubType;
1396
1397 // Add APP ID
1398 rtcpbuffer[pos++]=(WebRtc_UWord8)204;
1399
1400 WebRtc_UWord16 length = (_appLength>>2) + 2; // include SSRC and name
1401 rtcpbuffer[pos++]=(WebRtc_UWord8)(length>>8);
1402 rtcpbuffer[pos++]=(WebRtc_UWord8)(length);
1403
1404 // Add our own SSRC
1405 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1406 pos += 4;
1407
1408 // Add our application name
1409 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _appName);
1410 pos += 4;
1411
1412 // Add the data
1413 memcpy(rtcpbuffer +pos, _appData,_appLength);
1414 pos += _appLength;
1415 return 0;
1416}
1417
1418WebRtc_Word32
1419RTCPSender::BuildNACK(WebRtc_UWord8* rtcpbuffer,
1420 WebRtc_UWord32& pos,
1421 const WebRtc_Word32 nackSize,
1422 const WebRtc_UWord16* nackList)
1423{
1424 // sanity
1425 if(pos + 16 >= IP_PACKET_SIZE)
1426 {
1427 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
1428 return -2;
1429 }
1430
1431 // int size, WebRtc_UWord16* nackList
1432 // add nack list
1433 WebRtc_UWord8 FMT = 1;
1434 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
1435 rtcpbuffer[pos++]=(WebRtc_UWord8)205;
1436
1437 rtcpbuffer[pos++]=(WebRtc_UWord8) 0;
1438 int nackSizePos = pos;
1439 rtcpbuffer[pos++]=(WebRtc_UWord8)(3); //setting it to one kNACK signal as default
1440
1441 // Add our own SSRC
1442 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1443 pos += 4;
1444
1445 // Add the remote SSRC
1446 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1447 pos += 4;
1448
1449 // add the list
1450 int i = 0;
1451 int numOfNackFields = 0;
1452 while(nackSize > i && numOfNackFields < 253)
1453 {
1454 WebRtc_UWord16 nack = nackList[i];
1455 // put dow our sequence number
1456 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, nack);
1457 pos += 2;
1458
1459 i++;
1460 numOfNackFields++;
1461 if(nackSize > i)
1462 {
1463 bool moreThan16Away = (WebRtc_UWord16(nack+16) < nackList[i])?true: false;
1464 if(!moreThan16Away)
1465 {
1466 // check for a wrap
1467 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1468 {
1469 // wrap
1470 moreThan16Away = true;
1471 }
1472 }
1473 if(moreThan16Away)
1474 {
1475 // next is more than 16 away
1476 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1477 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1478 } else
1479 {
1480 // build our bitmask
1481 WebRtc_UWord16 bitmask = 0;
1482
1483 bool within16Away = (WebRtc_UWord16(nack+16) > nackList[i])?true: false;
1484 if(within16Away)
1485 {
1486 // check for a wrap
1487 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1488 {
1489 // wrap
1490 within16Away = false;
1491 }
1492 }
1493
1494 while( nackSize > i && within16Away)
1495 {
1496 WebRtc_Word16 shift = (nackList[i]-nack)-1;
1497 assert(!(shift > 15) && !(shift < 0));
1498
1499 bitmask += (1<< shift);
1500 i++;
1501 if(nackSize > i)
1502 {
1503 within16Away = (WebRtc_UWord16(nack+16) > nackList[i])?true: false;
1504 if(within16Away)
1505 {
1506 // check for a wrap
1507 if(WebRtc_UWord16(nack+16) > 0xff00 && nackList[i] < 0x0fff)
1508 {
1509 // wrap
1510 within16Away = false;
1511 }
1512 }
1513 }
1514 }
1515 ModuleRTPUtility::AssignUWord16ToBuffer(rtcpbuffer+pos, bitmask);
1516 pos += 2;
1517 }
1518 // sanity do we have room from one more 4 byte block?
1519 if(pos + 4 >= IP_PACKET_SIZE)
1520 {
1521 return -2;
1522 }
1523 } else
1524 {
1525 // no more in the list
1526 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1527 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1528 }
1529 }
1530 rtcpbuffer[nackSizePos]=(WebRtc_UWord8)(2+numOfNackFields);
1531 return 0;
1532}
1533
1534WebRtc_Word32
1535RTCPSender::BuildBYE(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1536{
1537 // sanity
1538 if(pos + 8 >= IP_PACKET_SIZE)
1539 {
1540 return -2;
1541 }
1542 if(_includeCSRCs)
1543 {
1544 // Add a bye packet
1545 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1 + _CSRCs; // number of SSRC+CSRCs
1546 rtcpbuffer[pos++]=(WebRtc_UWord8)203;
1547
1548 // length
1549 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1550 rtcpbuffer[pos++]=(WebRtc_UWord8)(1 + _CSRCs);
1551
1552 // Add our own SSRC
1553 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1554 pos += 4;
1555
1556 // add CSRCs
1557 for(int i = 0; i < _CSRCs; i++)
1558 {
1559 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _CSRC[i]);
1560 pos += 4;
1561 }
1562 } else
1563 {
1564 // Add a bye packet
1565 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + 1; // number of SSRC+CSRCs
1566 rtcpbuffer[pos++]=(WebRtc_UWord8)203;
1567
1568 // length
1569 rtcpbuffer[pos++]=(WebRtc_UWord8)0;
1570 rtcpbuffer[pos++]=(WebRtc_UWord8)1;
1571
1572 // Add our own SSRC
1573 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1574 pos += 4;
1575 }
1576 return 0;
1577}
1578
1579WebRtc_Word32
1580RTCPSender::BuildVoIPMetric(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
1581{
1582 // sanity
1583 if(pos + 44 >= IP_PACKET_SIZE)
1584 {
1585 return -2;
1586 }
1587
1588 // Add XR header
1589 rtcpbuffer[pos++]=(WebRtc_UWord8)0x80;
1590 rtcpbuffer[pos++]=(WebRtc_UWord8)207;
1591
1592 WebRtc_UWord32 XRLengthPos = pos;
1593
1594 // handle length later on
1595 pos++;
1596 pos++;
1597
1598 // Add our own SSRC
1599 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
1600 pos += 4;
1601
1602 // Add a VoIP metrics block
1603 rtcpbuffer[pos++]=7;
1604 rtcpbuffer[pos++]=0;
1605 rtcpbuffer[pos++]=0;
1606 rtcpbuffer[pos++]=8;
1607
1608 // Add the remote SSRC
1609 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
1610 pos += 4;
1611
1612 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1613 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1614 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1615 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1616
1617 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.burstDuration >> 8);
1618 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.burstDuration);
1619 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.gapDuration >> 8);
1620 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.gapDuration);
1621
1622 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.roundTripDelay >> 8);
1623 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.roundTripDelay);
1624 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.endSystemDelay >> 8);
1625 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.endSystemDelay);
1626
1627 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1628 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1629 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1630 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1631
1632 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1633 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1634 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1635 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1636
1637 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1638 rtcpbuffer[pos++] = 0; // reserved
1639 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBnominal >> 8);
1640 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBnominal);
1641
1642 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBmax >> 8);
1643 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBmax);
1644 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBabsMax >> 8);
1645 rtcpbuffer[pos++] = (WebRtc_UWord8)(_xrVoIPMetric.JBabsMax);
1646
1647 rtcpbuffer[XRLengthPos]=(WebRtc_UWord8)(0);
1648 rtcpbuffer[XRLengthPos+1]=(WebRtc_UWord8)(10);
1649 return 0;
1650}
1651
1652WebRtc_Word32
1653RTCPSender::SendRTCP(const WebRtc_UWord32 packetTypeFlags,
1654 const WebRtc_Word32 nackSize, // NACK
1655 const WebRtc_UWord16* nackList, // NACK
1656 const WebRtc_UWord32 RTT, // FIR
1657 const WebRtc_UWord64 pictureID) // SLI & RPSI
1658{
1659 WebRtc_UWord32 rtcpPacketTypeFlags = packetTypeFlags;
1660 WebRtc_UWord32 pos = 0;
1661 WebRtc_UWord8 rtcpbuffer[IP_PACKET_SIZE];
1662
niklase@google.com470e71d2011-07-07 08:21:25 +00001663 do // only to be able to use break :) (and the critsect must be inside its own scope)
1664 {
1665 // collect the received information
1666 RTCPReportBlock received;
1667 bool hasReceived = false;
1668 WebRtc_UWord32 NTPsec = 0;
1669 WebRtc_UWord32 NTPfrac = 0;
xians@webrtc.org8738d272011-11-25 13:43:53 +00001670 bool rtcpCompound = false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001671 WebRtc_UWord32 jitterTransmissionOffset = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001672
xians@webrtc.org8738d272011-11-25 13:43:53 +00001673 {
1674 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1675 if(_method == kRtcpOff)
1676 {
1677 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1678 "%s invalid state", __FUNCTION__);
1679 return -1;
1680 }
1681 rtcpCompound = (_method == kRtcpCompound) ? true : false;
1682 }
1683
1684 if (rtcpCompound ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001685 rtcpPacketTypeFlags & kRtcpReport ||
1686 rtcpPacketTypeFlags & kRtcpSr ||
1687 rtcpPacketTypeFlags & kRtcpRr)
1688 {
1689 // get statistics from our RTPreceiver outside critsect
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001690 if(_rtpRtcp.ReportBlockStatistics(&received.fractionLost,
1691 &received.cumulativeLost,
1692 &received.extendedHighSeqNum,
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001693 &received.jitter,
1694 &jitterTransmissionOffset) == 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001695 {
1696 hasReceived = true;
1697
1698 WebRtc_UWord32 lastReceivedRRNTPsecs = 0;
1699 WebRtc_UWord32 lastReceivedRRNTPfrac = 0;
1700 WebRtc_UWord32 remoteSR = 0;
1701
1702 // ok even if we have not received a SR, we will send 0 in that case
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001703 _rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
1704 lastReceivedRRNTPfrac,
1705 remoteSR);
niklase@google.com470e71d2011-07-07 08:21:25 +00001706
1707 // get our NTP as late as possible to avoid a race
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001708 _clock.CurrentNTP(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001709
1710 // Delay since last received report
1711 WebRtc_UWord32 delaySinceLastReceivedSR = 0;
1712 if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
1713 {
1714 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1715 WebRtc_UWord32 now=NTPsec&0x0000FFFF;
1716 now <<=16;
1717 now += (NTPfrac&0xffff0000)>>16;
1718
1719 WebRtc_UWord32 receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
1720 receiveTime <<=16;
1721 receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
1722
1723 delaySinceLastReceivedSR = now-receiveTime;
1724 }
1725 received.delaySinceLastSR = delaySinceLastReceivedSR;
1726 received.lastSR = remoteSR;
1727 } else
1728 {
1729 // we need to send our NTP even if we dont have received any reports
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001730 _clock.CurrentNTP(NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +00001731 }
1732 }
1733
1734 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1735
1736 if(_TMMBR ) // attach TMMBR to send and receive reports
1737 {
1738 rtcpPacketTypeFlags |= kRtcpTmmbr;
1739 }
1740 if(_appSend)
1741 {
1742 rtcpPacketTypeFlags |= kRtcpApp;
1743 _appSend = false;
1744 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001745 if(_REMB && _sendREMB)
1746 {
mflodman@webrtc.org84dc3d12011-12-22 10:26:13 +00001747 // Always attach REMB to SR if that is configured. Note that REMB is
1748 // only sent on one of the RTP modules in the REMB group.
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001749 rtcpPacketTypeFlags |= kRtcpRemb;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001750 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001751 if(_xrSendVoIPMetric)
1752 {
1753 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1754 _xrSendVoIPMetric = false;
1755 }
1756 if(_sendTMMBN) // set when having received a TMMBR
1757 {
1758 rtcpPacketTypeFlags |= kRtcpTmmbn;
1759 _sendTMMBN = false;
1760 }
1761
1762 if(_method == kRtcpCompound)
1763 {
1764 if(_sending)
1765 {
1766 rtcpPacketTypeFlags |= kRtcpSr;
1767 } else
1768 {
1769 rtcpPacketTypeFlags |= kRtcpRr;
1770 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001771 if (_IJ && hasReceived)
1772 {
1773 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1774 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001775 } else if(_method == kRtcpNonCompound)
1776 {
1777 if(rtcpPacketTypeFlags & kRtcpReport)
1778 {
1779 if(_sending)
1780 {
1781 rtcpPacketTypeFlags |= kRtcpSr;
1782 } else
1783 {
1784 rtcpPacketTypeFlags |= kRtcpRr;
1785 }
1786 }
1787 }
1788 if( rtcpPacketTypeFlags & kRtcpRr ||
1789 rtcpPacketTypeFlags & kRtcpSr)
1790 {
1791 // generate next time to send a RTCP report
1792 // seeded from RTP constructor
1793 WebRtc_Word32 random = rand() % 1000;
1794 WebRtc_Word32 timeToNext = RTCP_INTERVAL_AUDIO_MS;
1795
1796 if(_audio)
1797 {
1798 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
1799 }else
1800 {
1801 WebRtc_UWord32 minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1802 if(_sending)
1803 {
1804 // calc bw for video 360/sendBW in kbit/s
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001805 WebRtc_UWord32 sendBitrateKbit = 0;
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001806 WebRtc_UWord32 videoRate = 0;
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001807 WebRtc_UWord32 fecRate = 0;
1808 WebRtc_UWord32 nackRate = 0;
1809 _rtpRtcp.BitrateSent(&sendBitrateKbit,
stefan@webrtc.orgfbea4e52011-10-27 16:08:29 +00001810 &videoRate,
stefan@webrtc.orgd0bdab02011-10-14 14:24:54 +00001811 &fecRate,
1812 &nackRate);
1813 sendBitrateKbit /= 1000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001814 if(sendBitrateKbit != 0)
1815 {
1816 minIntervalMs = 360000/sendBitrateKbit;
1817 }
1818 }
1819 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1820 {
1821 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1822 }
1823 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1824 }
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00001825 _nextTimeToSendRTCP = _clock.GetTimeInMS() + timeToNext;
niklase@google.com470e71d2011-07-07 08:21:25 +00001826 }
1827
1828 // if the data does not fitt in the packet we fill it as much as possible
1829 WebRtc_Word32 buildVal = 0;
1830
1831 if(rtcpPacketTypeFlags & kRtcpSr)
1832 {
1833 if(hasReceived)
1834 {
1835 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
1836 } else
1837 {
1838 buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac);
1839 }
1840 if(buildVal == -1)
1841 {
1842 return -1; // error
1843
1844 }else if(buildVal == -2)
1845 {
1846 break; // out of buffer
1847 }
1848 buildVal = BuildSDEC(rtcpbuffer, pos);
1849 if(buildVal == -1)
1850 {
1851 return -1; // error
1852
1853 }else if(buildVal == -2)
1854 {
1855 break; // out of buffer
1856 }
1857
1858 }else if(rtcpPacketTypeFlags & kRtcpRr)
1859 {
1860 if(hasReceived)
1861 {
1862 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
1863 }else
1864 {
1865 buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
1866 }
1867 if(buildVal == -1)
1868 {
1869 return -1; // error
1870
1871 }else if(buildVal == -2)
1872 {
1873 break; // out of buffer
1874 }
1875 // only of set
1876 if(_CNAME[0] != 0)
1877 {
1878 buildVal = BuildSDEC(rtcpbuffer, pos);
1879 if(buildVal == -1)
1880 {
1881 return -1; // error
1882 }
1883 }
1884 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001885 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1886 {
1887 // If present, this RTCP packet must be placed after a
1888 // receiver report.
1889 buildVal = BuildExtendedJitterReport(rtcpbuffer,
1890 pos,
1891 jitterTransmissionOffset);
1892 if(buildVal == -1)
1893 {
1894 return -1; // error
1895 }
1896 else if(buildVal == -2)
1897 {
1898 break; // out of buffer
1899 }
1900 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001901 if(rtcpPacketTypeFlags & kRtcpPli)
1902 {
1903 buildVal = BuildPLI(rtcpbuffer, pos);
1904 if(buildVal == -1)
1905 {
1906 return -1; // error
1907
1908 }else if(buildVal == -2)
1909 {
1910 break; // out of buffer
1911 }
1912 }
1913 if(rtcpPacketTypeFlags & kRtcpFir)
1914 {
1915 buildVal = BuildFIR(rtcpbuffer, pos, RTT);
1916 if(buildVal == -1)
1917 {
1918 return -1; // error
1919
1920 }else if(buildVal == -2)
1921 {
1922 break; // out of buffer
1923 }
1924 }
1925 if(rtcpPacketTypeFlags & kRtcpSli)
1926 {
1927 buildVal = BuildSLI(rtcpbuffer, pos, (WebRtc_UWord8)pictureID);
1928 if(buildVal == -1)
1929 {
1930 return -1; // error
1931
1932 }else if(buildVal == -2)
1933 {
1934 break; // out of buffer
1935 }
1936 }
1937 if(rtcpPacketTypeFlags & kRtcpRpsi)
1938 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001939 const WebRtc_Word8 payloadType = _rtpRtcp.SendPayloadType();
niklase@google.com470e71d2011-07-07 08:21:25 +00001940 if(payloadType == -1)
1941 {
1942 return -1;
1943 }
1944 buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (WebRtc_UWord8)payloadType);
1945 if(buildVal == -1)
1946 {
1947 return -1; // error
1948
1949 }else if(buildVal == -2)
1950 {
1951 break; // out of buffer
1952 }
1953 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001954 if(rtcpPacketTypeFlags & kRtcpRemb)
1955 {
1956 buildVal = BuildREMB(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 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001966 if(rtcpPacketTypeFlags & kRtcpBye)
1967 {
1968 buildVal = BuildBYE(rtcpbuffer, pos);
1969 if(buildVal == -1)
1970 {
1971 return -1; // error
1972
1973 }else if(buildVal == -2)
1974 {
1975 break; // out of buffer
1976 }
1977 }
1978 if(rtcpPacketTypeFlags & kRtcpApp)
1979 {
1980 buildVal = BuildAPP(rtcpbuffer, pos);
1981 if(buildVal == -1)
1982 {
1983 return -1; // error
1984
1985 }else if(buildVal == -2)
1986 {
1987 break; // out of buffer
1988 }
1989 }
1990 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1991 {
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001992 buildVal = BuildTMMBR(rtcpbuffer, pos);
niklase@google.com470e71d2011-07-07 08:21:25 +00001993 if(buildVal == -1)
1994 {
1995 return -1; // error
1996
1997 }else if(buildVal == -2)
1998 {
1999 break; // out of buffer
2000 }
2001 }
2002 if(rtcpPacketTypeFlags & kRtcpTmmbn)
2003 {
2004 buildVal = BuildTMMBN(rtcpbuffer, pos);
2005 if(buildVal == -1)
2006 {
2007 return -1; // error
2008
2009 }else if(buildVal == -2)
2010 {
2011 break; // out of buffer
2012 }
2013 }
2014 if(rtcpPacketTypeFlags & kRtcpNack)
2015 {
2016 buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList);
2017 if(buildVal == -1)
2018 {
2019 return -1; // error
2020
2021 }else if(buildVal == -2)
2022 {
2023 break; // out of buffer
2024 }
2025 }
2026 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
2027 {
2028 buildVal = BuildVoIPMetric(rtcpbuffer, pos);
2029 if(buildVal == -1)
2030 {
2031 return -1; // error
2032
2033 }else if(buildVal == -2)
2034 {
2035 break; // out of buffer
2036 }
2037 }
2038 }while (false);
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00002039 // Sanity don't send empty packets.
2040 if (pos == 0)
2041 {
2042 return -1;
2043 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002044 return SendToNetwork(rtcpbuffer, (WebRtc_UWord16)pos);
2045}
2046
2047WebRtc_Word32
2048RTCPSender::SendToNetwork(const WebRtc_UWord8* dataBuffer,
2049 const WebRtc_UWord16 length)
2050{
2051 CriticalSectionScoped lock(_criticalSectionTransport);
2052 if(_cbTransport)
2053 {
2054 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
2055 {
2056 return 0;
2057 }
2058 }
2059 return -1;
2060}
2061
2062WebRtc_Word32
2063RTCPSender::SetCSRCStatus(const bool include)
2064{
2065 _includeCSRCs = include;
2066 return 0;
2067}
2068
2069WebRtc_Word32
2070RTCPSender::SetCSRCs(const WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize],
2071 const WebRtc_UWord8 arrLength)
2072{
2073 if(arrLength > kRtpCsrcSize)
2074 {
2075 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2076 assert(false);
2077 return -1;
2078 }
2079
2080 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2081
2082 for(int i = 0; i < arrLength;i++)
2083 {
2084 _CSRC[i] = arrOfCSRC[i];
2085 }
2086 _CSRCs = arrLength;
2087 return 0;
2088}
2089
2090WebRtc_Word32
2091RTCPSender::SetApplicationSpecificData(const WebRtc_UWord8 subType,
2092 const WebRtc_UWord32 name,
2093 const WebRtc_UWord8* data,
2094 const WebRtc_UWord16 length)
2095{
2096 if(length %4 != 0)
2097 {
2098 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2099 return -1;
2100 }
2101 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2102
2103 if(_appData)
2104 {
2105 delete [] _appData;
2106 }
2107
2108 _appSend = true;
2109 _appSubType = subType;
2110 _appName = name;
2111 _appData = new WebRtc_UWord8[length];
2112 _appLength = length;
2113 memcpy(_appData, data, length);
2114 return 0;
2115}
2116
2117WebRtc_Word32
2118RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
2119{
2120 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2121 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2122
2123 _xrSendVoIPMetric = true;
2124 return 0;
2125}
2126
2127// called under critsect _criticalSectionRTCPSender
2128WebRtc_Word32
2129RTCPSender::AddReportBlocks(WebRtc_UWord8* rtcpbuffer,
2130 WebRtc_UWord32& pos,
2131 WebRtc_UWord8& numberOfReportBlocks,
2132 const RTCPReportBlock* received,
2133 const WebRtc_UWord32 NTPsec,
2134 const WebRtc_UWord32 NTPfrac)
2135{
2136 // sanity one block
2137 if(pos + 24 >= IP_PACKET_SIZE)
2138 {
2139 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2140 return -1;
2141 }
2142
2143 numberOfReportBlocks = _reportBlocks.Size();
2144 if(received)
2145 {
2146 // add our multiple RR to numberOfReportBlocks
2147 numberOfReportBlocks++;
2148 }
2149
2150 if(received)
2151 {
2152 // answer to the one that sends to me
2153 _lastRTCPTime[0] = ModuleRTPUtility::ConvertNTPTimeToMS(NTPsec, NTPfrac);
2154
2155 // Remote SSRC
2156 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
2157 pos += 4;
2158
2159 // fraction lost
2160 rtcpbuffer[pos++]=received->fractionLost;
2161
2162 // cumulative loss
2163 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos, received->cumulativeLost);
2164 pos += 3;
2165
2166 // extended highest seq_no, contain the highest sequence number received
2167 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->extendedHighSeqNum);
2168 pos += 4;
2169
2170 //Jitter
2171 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
2172 pos += 4;
2173
2174 // Last SR timestamp, our NTP time when we received the last report
2175 // This is the value that we read from the send report packet not when we received it...
2176 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
2177 pos += 4;
2178
2179 // Delay since last received report,time since we received the report
2180 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->delaySinceLastSR);
2181 pos += 4;
2182 }
2183
2184 if(pos + _reportBlocks.Size()*24 >= IP_PACKET_SIZE)
2185 {
2186 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
2187 return -1;
2188 }
2189
2190 MapItem* item = _reportBlocks.First();
2191 for(int i = 0; i < _reportBlocks.Size() && item; i++)
2192 {
2193 // we can have multiple report block in a conference
2194 WebRtc_UWord32 remoteSSRC = item->GetId();
2195 RTCPReportBlock* reportBlock = (RTCPReportBlock*)item->GetItem();
2196 if(reportBlock)
2197 {
2198 // Remote SSRC
2199 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
2200 pos += 4;
2201
2202 // fraction lost
2203 rtcpbuffer[pos++]=(WebRtc_UWord8)(reportBlock->fractionLost);
2204
2205 // cumulative loss
2206 ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos, reportBlock->cumulativeLost);
2207 pos += 3;
2208
2209 // extended highest seq_no, contain the highest sequence number received
2210 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, reportBlock->extendedHighSeqNum);
2211 pos += 4;
2212
2213 //Jitter
2214 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, reportBlock->jitter);
2215 pos += 4;
2216
2217 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, reportBlock->lastSR);
2218 pos += 4;
2219
2220 ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, reportBlock->delaySinceLastSR);
2221 pos += 4;
2222 }
2223 item = _reportBlocks.Next(item);
2224 }
2225 return pos;
2226}
2227
2228// no callbacks allowed inside this function
2229WebRtc_Word32
2230RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
2231 const WebRtc_UWord32 maxBitrateKbit)
2232{
2233 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2234
2235 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2236 {
2237 _sendTMMBN = true;
2238 return 0;
2239 }
2240 return -1;
2241}
2242
2243WebRtc_Word32
2244RTCPSender::RequestTMMBR(WebRtc_UWord32 estimatedBW, WebRtc_UWord32 packetOH)
2245{
2246 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2247 if(_TMMBR)
2248 {
2249 _tmmbr_Send = estimatedBW;
2250 _packetOH_Send = packetOH;
2251
2252 return 0;
2253 }
2254 return -1;
2255}
2256
2257RateControlRegion
2258RTCPSender::UpdateOverUseState(const RateControlInput& rateControlInput, bool& firstOverUse)
2259{
2260 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +00002261 return _remoteRateControl.Update(rateControlInput, firstOverUse,
2262 _clock.GetTimeInMS());
niklase@google.com470e71d2011-07-07 08:21:25 +00002263}
2264} // namespace webrtc