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