| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |  This file is a part of JRTPLIB | 
					
						
							|  |  |  |  Copyright (c) 1999-2017 Jori Liesenborgs | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |  Contact: jori.liesenborgs@gmail.com | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |  This library was developed at the Expertise Centre for Digital Media | 
					
						
							|  |  |  |  (http://www.edm.uhasselt.be), a research center of the Hasselt University
 | 
					
						
							|  |  |  |  (http://www.uhasselt.be). The library is based upon work done for
 | 
					
						
							|  |  |  |  my thesis at the School for Knowledge Technology (Belgium/The Netherlands). | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |  Permission is hereby granted, free of charge, to any person obtaining a | 
					
						
							|  |  |  |  copy of this software and associated documentation files (the "Software"), | 
					
						
							|  |  |  |  to deal in the Software without restriction, including without limitation | 
					
						
							|  |  |  |  the rights to use, copy, modify, merge, publish, distribute, sublicense, | 
					
						
							|  |  |  |  and/or sell copies of the Software, and to permit persons to whom the | 
					
						
							|  |  |  |  Software is furnished to do so, subject to the following conditions: | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |  The above copyright notice and this permission notice shall be included | 
					
						
							|  |  |  |  in all copies or substantial portions of the Software. | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | 
					
						
							|  |  |  |  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
					
						
							|  |  |  |  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL | 
					
						
							|  |  |  |  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
					
						
							|  |  |  |  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | 
					
						
							|  |  |  |  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | 
					
						
							|  |  |  |  IN THE SOFTWARE. | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "rtcpscheduler.h"
 | 
					
						
							|  |  |  | #include "rtpsources.h"
 | 
					
						
							|  |  |  | #include "rtpdefines.h"
 | 
					
						
							|  |  |  | #include "rtcppacket.h"
 | 
					
						
							|  |  |  | #include "rtppacket.h"
 | 
					
						
							|  |  |  | #include "rtcpcompoundpacket.h"
 | 
					
						
							|  |  |  | #include "rtpsourcedata.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define RTCPSCHED_MININTERVAL						1.0
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace qrtplib | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  | RTCPSchedulerParams::RTCPSchedulerParams() : | 
					
						
							|  |  |  |         mininterval(RTCP_DEFAULTMININTERVAL) | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     bandwidth = 1000; // TODO What is a good value here?
 | 
					
						
							|  |  |  |     senderfraction = RTCP_DEFAULTSENDERFRACTION; | 
					
						
							|  |  |  |     usehalfatstartup = RTCP_DEFAULTHALFATSTARTUP; | 
					
						
							|  |  |  |     immediatebye = RTCP_DEFAULTIMMEDIATEBYE; | 
					
						
							|  |  |  |     timeinit.Dummy(); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | RTCPSchedulerParams::~RTCPSchedulerParams() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int RTCPSchedulerParams::SetRTCPBandwidth(double bw) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (bw < 0.0) | 
					
						
							|  |  |  |         return ERR_RTP_SCHEDPARAMS_INVALIDBANDWIDTH; | 
					
						
							|  |  |  |     bandwidth = bw; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int RTCPSchedulerParams::SetSenderBandwidthFraction(double fraction) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (fraction < 0.0 || fraction > 1.0) | 
					
						
							|  |  |  |         return ERR_RTP_SCHEDPARAMS_BADFRACTION; | 
					
						
							|  |  |  |     senderfraction = fraction; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int RTCPSchedulerParams::SetMinimumTransmissionInterval(const RTPTime &t) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     double t2 = t.GetDouble(); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (t2 < RTCPSCHED_MININTERVAL) | 
					
						
							|  |  |  |         return ERR_RTP_SCHEDPARAMS_BADMINIMUMINTERVAL; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     mininterval = t; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  | RTCPScheduler::RTCPScheduler(RTPSources &s, RTPRandom &r) : | 
					
						
							|  |  |  |         sources(s), nextrtcptime(0, 0), prevrtcptime(0, 0), rtprand(r) | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     Reset(); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     //std::cout << (void *)(&rtprand) << std::endl;
 | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | RTCPScheduler::~RTCPScheduler() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void RTCPScheduler::Reset() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     headeroverhead = 0; // user has to set this to an appropriate value
 | 
					
						
							|  |  |  |     hassentrtcp = false; | 
					
						
							|  |  |  |     firstcall = true; | 
					
						
							|  |  |  |     avgrtcppacksize = 1000; // TODO: what is a good value for this?
 | 
					
						
							|  |  |  |     byescheduled = false; | 
					
						
							|  |  |  |     sendbyenow = false; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void RTCPScheduler::AnalyseIncoming(RTCPCompoundPacket &rtcpcomppack) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     bool isbye = false; | 
					
						
							|  |  |  |     RTCPPacket *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rtcpcomppack.GotoFirstPacket(); | 
					
						
							|  |  |  |     while (!isbye && ((p = rtcpcomppack.GetNextPacket()) != 0)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (p->GetPacketType() == RTCPPacket::BYE) | 
					
						
							|  |  |  |             isbye = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!isbye) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-02-28 13:31:44 +01:00
										 |  |  |         std::size_t packsize = headeroverhead + rtcpcomppack.GetCompoundPacketLength(); | 
					
						
							|  |  |  |         avgrtcppacksize = (std::size_t)((1.0 / 16.0) * ((double) packsize) + (15.0 / 16.0) * ((double) avgrtcppacksize)); | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (byescheduled) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2018-02-28 13:31:44 +01:00
										 |  |  |             std::size_t packsize = headeroverhead + rtcpcomppack.GetCompoundPacketLength(); | 
					
						
							|  |  |  |             avgbyepacketsize = (std::size_t)((1.0 / 16.0) * ((double) packsize) + (15.0 / 16.0) * ((double) avgbyepacketsize)); | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |             byemembers++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void RTCPScheduler::AnalyseOutgoing(RTCPCompoundPacket &rtcpcomppack) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     bool isbye = false; | 
					
						
							|  |  |  |     RTCPPacket *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rtcpcomppack.GotoFirstPacket(); | 
					
						
							|  |  |  |     while (!isbye && ((p = rtcpcomppack.GetNextPacket()) != 0)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (p->GetPacketType() == RTCPPacket::BYE) | 
					
						
							|  |  |  |             isbye = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!isbye) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-02-28 13:31:44 +01:00
										 |  |  |         std::size_t packsize = headeroverhead + rtcpcomppack.GetCompoundPacketLength(); | 
					
						
							|  |  |  |         avgrtcppacksize = (std::size_t)((1.0 / 16.0) * ((double) packsize) + (15.0 / 16.0) * ((double) avgrtcppacksize)); | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     hassentrtcp = true; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | RTPTime RTCPScheduler::GetTransmissionDelay() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (firstcall) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         firstcall = false; | 
					
						
							|  |  |  |         prevrtcptime = RTPTime::CurrentTime(); | 
					
						
							|  |  |  |         pmembers = sources.GetActiveMemberCount(); | 
					
						
							|  |  |  |         CalculateNextRTCPTime(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     RTPTime curtime = RTPTime::CurrentTime(); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (curtime > nextrtcptime) // packet should be sent
 | 
					
						
							|  |  |  |         return RTPTime(0, 0); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     RTPTime diff = nextrtcptime; | 
					
						
							|  |  |  |     diff -= curtime; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     return diff; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool RTCPScheduler::IsTime() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (firstcall) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         firstcall = false; | 
					
						
							|  |  |  |         prevrtcptime = RTPTime::CurrentTime(); | 
					
						
							|  |  |  |         pmembers = sources.GetActiveMemberCount(); | 
					
						
							|  |  |  |         CalculateNextRTCPTime(); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     RTPTime currenttime = RTPTime::CurrentTime(); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | //	// TODO: for debugging
 | 
					
						
							|  |  |  | //	double diff = nextrtcptime.GetDouble() - currenttime.GetDouble();
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	std::cout << "Delay till next RTCP interval: " << diff << std::endl;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (currenttime < nextrtcptime) // timer has not yet expired
 | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     RTPTime checktime(0, 0); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (!byescheduled) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         bool aresender = false; | 
					
						
							|  |  |  |         RTPSourceData *srcdat; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |         if ((srcdat = sources.GetOwnSourceInfo()) != 0) | 
					
						
							|  |  |  |             aresender = srcdat->IsSender(); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |         checktime = CalculateTransmissionInterval(aresender); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         checktime = CalculateBYETransmissionInterval(); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | //	std::cout << "Calculated checktime: " << checktime.GetDouble() << std::endl;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     checktime += prevrtcptime; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (checktime <= currenttime) // Okay
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         byescheduled = false; | 
					
						
							|  |  |  |         prevrtcptime = currenttime; | 
					
						
							|  |  |  |         pmembers = sources.GetActiveMemberCount(); | 
					
						
							|  |  |  |         CalculateNextRTCPTime(); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | //	std::cout << "New delay: " << nextrtcptime.GetDouble() - currenttime.GetDouble() << std::endl;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     nextrtcptime = checktime; | 
					
						
							|  |  |  |     pmembers = sources.GetActiveMemberCount(); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void RTCPScheduler::CalculateNextRTCPTime() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     bool aresender = false; | 
					
						
							|  |  |  |     RTPSourceData *srcdat; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if ((srcdat = sources.GetOwnSourceInfo()) != 0) | 
					
						
							|  |  |  |         aresender = srcdat->IsSender(); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     nextrtcptime = RTPTime::CurrentTime(); | 
					
						
							|  |  |  |     nextrtcptime += CalculateTransmissionInterval(aresender); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | RTPTime RTCPScheduler::CalculateDeterministicInterval(bool sender /* = false */) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     int numsenders = sources.GetSenderCount(); | 
					
						
							|  |  |  |     int numtotal = sources.GetActiveMemberCount(); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | //	std::cout << "CalculateDeterministicInterval" << std::endl;
 | 
					
						
							|  |  |  | //	std::cout << "  numsenders: " << numsenders << std::endl;
 | 
					
						
							|  |  |  | //	std::cout << "  numtotal: " << numtotal << std::endl;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     // Try to avoid division by zero:
 | 
					
						
							|  |  |  |     if (numtotal == 0) | 
					
						
							|  |  |  |         numtotal++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     double sfraction = ((double) numsenders) / ((double) numtotal); | 
					
						
							|  |  |  |     double C, n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (sfraction <= schedparams.GetSenderBandwidthFraction()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (sender) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             C = ((double) avgrtcppacksize) / (schedparams.GetSenderBandwidthFraction() * schedparams.GetRTCPBandwidth()); | 
					
						
							|  |  |  |             n = (double) numsenders; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             C = ((double) avgrtcppacksize) / ((1.0 - schedparams.GetSenderBandwidthFraction()) * schedparams.GetRTCPBandwidth()); | 
					
						
							|  |  |  |             n = (double) (numtotal - numsenders); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         C = ((double) avgrtcppacksize) / schedparams.GetRTCPBandwidth(); | 
					
						
							|  |  |  |         n = (double) numtotal; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     RTPTime Tmin = schedparams.GetMinimumTransmissionInterval(); | 
					
						
							|  |  |  |     double tmin = Tmin.GetDouble(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!hassentrtcp && schedparams.GetUseHalfAtStartup()) | 
					
						
							|  |  |  |         tmin /= 2.0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     double ntimesC = n * C; | 
					
						
							|  |  |  |     double Td = (tmin > ntimesC) ? tmin : ntimesC; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // TODO: for debugging
 | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | //	std::cout << "  Td: " << Td << std::endl;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     return RTPTime(Td); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | RTPTime RTCPScheduler::CalculateTransmissionInterval(bool sender) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     RTPTime Td = CalculateDeterministicInterval(sender); | 
					
						
							|  |  |  |     double td, mul, T; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | //	std::cout << "CalculateTransmissionInterval" << std::endl;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     td = Td.GetDouble(); | 
					
						
							|  |  |  |     mul = rtprand.GetRandomDouble() + 0.5; // gives random value between 0.5 and 1.5
 | 
					
						
							|  |  |  |     T = (td * mul) / 1.21828; // see RFC 3550 p 30
 | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | //	std::cout << "  Td: " << td << std::endl;
 | 
					
						
							|  |  |  | //	std::cout << "  mul: " << mul << std::endl;
 | 
					
						
							|  |  |  | //	std::cout << "  T: " << T << std::endl;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     return RTPTime(T); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void RTCPScheduler::PerformReverseReconsideration() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (firstcall) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     double diff1, diff2; | 
					
						
							|  |  |  |     int members = sources.GetActiveMemberCount(); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     RTPTime tc = RTPTime::CurrentTime(); | 
					
						
							|  |  |  |     RTPTime tn_min_tc = nextrtcptime; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (tn_min_tc > tc) | 
					
						
							|  |  |  |         tn_min_tc -= tc; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         tn_min_tc = RTPTime(0, 0); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | //	std::cout << "+tn_min_tc0 " << nextrtcptime.GetDouble()-tc.GetDouble() << std::endl;
 | 
					
						
							|  |  |  | //	std::cout << "-tn_min_tc0 " << -nextrtcptime.GetDouble()+tc.GetDouble() << std::endl;
 | 
					
						
							|  |  |  | //	std::cout << "tn_min_tc " << tn_min_tc.GetDouble() << std::endl;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     RTPTime tc_min_tp = tc; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (tc_min_tp > prevrtcptime) | 
					
						
							|  |  |  |         tc_min_tp -= prevrtcptime; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         tc_min_tp = 0; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (pmembers == 0) // avoid division by zero
 | 
					
						
							|  |  |  |         pmembers++; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     diff1 = (((double) members) / ((double) pmembers)) * tn_min_tc.GetDouble(); | 
					
						
							|  |  |  |     diff2 = (((double) members) / ((double) pmembers)) * tc_min_tp.GetDouble(); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     nextrtcptime = tc; | 
					
						
							|  |  |  |     prevrtcptime = tc; | 
					
						
							|  |  |  |     nextrtcptime += RTPTime(diff1); | 
					
						
							|  |  |  |     prevrtcptime -= RTPTime(diff2); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     pmembers = members; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-28 13:31:44 +01:00
										 |  |  | void RTCPScheduler::ScheduleBYEPacket(std::size_t packetsize) | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (byescheduled) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (firstcall) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         firstcall = false; | 
					
						
							|  |  |  |         pmembers = sources.GetActiveMemberCount(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     byescheduled = true; | 
					
						
							|  |  |  |     avgbyepacketsize = packetsize + headeroverhead; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     // For now, we will always use the BYE backoff algorithm as described in rfc 3550 p 33
 | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     byemembers = 1; | 
					
						
							|  |  |  |     pbyemembers = 1; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (schedparams.GetRequestImmediateBYE() && sources.GetActiveMemberCount() < 50) // p 34 (top)
 | 
					
						
							|  |  |  |         sendbyenow = true; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         sendbyenow = false; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     prevrtcptime = RTPTime::CurrentTime(); | 
					
						
							|  |  |  |     nextrtcptime = prevrtcptime; | 
					
						
							|  |  |  |     nextrtcptime += CalculateBYETransmissionInterval(); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void RTCPScheduler::ActiveMemberDecrease() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (sources.GetActiveMemberCount() < pmembers) | 
					
						
							|  |  |  |         PerformReverseReconsideration(); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | RTPTime RTCPScheduler::CalculateBYETransmissionInterval() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (!byescheduled) | 
					
						
							|  |  |  |         return RTPTime(0, 0); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (sendbyenow) | 
					
						
							|  |  |  |         return RTPTime(0, 0); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     double C, n; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     C = ((double) avgbyepacketsize) / ((1.0 - schedparams.GetSenderBandwidthFraction()) * schedparams.GetRTCPBandwidth()); | 
					
						
							|  |  |  |     n = (double) byemembers; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     RTPTime Tmin = schedparams.GetMinimumTransmissionInterval(); | 
					
						
							|  |  |  |     double tmin = Tmin.GetDouble(); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     if (schedparams.GetUseHalfAtStartup()) | 
					
						
							|  |  |  |         tmin /= 2.0; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     double ntimesC = n * C; | 
					
						
							|  |  |  |     double Td = (tmin > ntimesC) ? tmin : ntimesC; | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     double mul = rtprand.GetRandomDouble() + 0.5; // gives random value between 0.5 and 1.5
 | 
					
						
							|  |  |  |     double T = (Td * mul) / 1.21828; // see RFC 3550 p 30
 | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 23:05:46 +01:00
										 |  |  |     return RTPTime(T); | 
					
						
							| 
									
										
										
										
											2018-02-27 01:35:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // end namespace
 | 
					
						
							|  |  |  | 
 |