/*---------------------------------------------------------------------------- * File: RTCPTIME.C * Product: RTP/RTCP implementation * Description: Provides timers related functions for RTCP. * * INTEL Corporation Proprietary Information * This listing is supplied under the terms of a license agreement with * Intel Corporation and may not be copied nor disclosed except in * accordance with the terms of that agreement. * Copyright (c) 1995 Intel Corporation. *--------------------------------------------------------------------------*/ #include "rrcm.h" /*--------------------------------------------------------------------------- / Global Variables /--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- / External Variables /--------------------------------------------------------------------------*/ extern PRTCP_CONTEXT pRTCPContext; #ifdef _DEBUG extern char debug_string[]; #endif /*---------------------------------------------------------------------------- * Function : RTCPxmitInterval * Description: Calculate the RTCP transmission interval * * Input : members: Estimated number of session members including * ourselves. On the initial call, should be 1. * * senders: Number of active senders since last report, known from * construction of receiver reports for this packet. * Includes ourselves if we sent. * * rtcpBw: The target RTCP bandwidth, ie, the total Bw that will * be used by RTCP by all members of this session, in * bytes per seconds. Should be 5% of the session Bw. * * weSent: True if we've sent data during the last two RTCP * intervals. If TRUE, the compound RTCP packet just * sent contained an SR packet. * * packetSize: Size of the RTCP packet just sent, in bytes, including * network encapsulation, eg 28 bytes for UDP over IP. * * *avgRtcpSize: Estimator to RTCP packet size, initialized and * updated by this function for the packet just sent. * * initial: Initial transmission flag. * * Return: Interval time before the next transmission in msec. ---------------------------------------------------------------------------*/ DWORD RTCPxmitInterval (DWORD members, DWORD senders, DWORD rtcpBw, DWORD weSent, DWORD packetSize, int *avgRtcpSize, DWORD initial) { #ifdef ENABLE_FLOATING_POINT // // Minimum time between RTCP packets from this site in seconds. This time // // prevents the reports from clumping when sessions are small and the law // // of large numbers isn't helping to smooth out the traffic. It also keeps // // the report intervals from becoming ridiculously small during transient // // outages like a network partition. // double const RTCP_MinTime = 5.; // // // Fraction of the RTCP bandwidth to be shared among active senders. This // // fraction was chosen so that in a typical session with one or two active // // senders, the computed report time would be roughly equal to the minimum // // report time so that we don't unnecessarily slow down receiver reports. // // The receiver fraction must be 1 - the sender fraction. // double const RTCP_SenderBwFraction = 0.25; // double const RTCP_RcvrBwFraction = (1 - RTCP_SenderBwFraction); // // // Gain (smoothing constant) for the low-pass filter that estimates the // // average RTCP packet size. // double const RTCP_sizeGain = RTCP_SIZE_GAIN; // // // Interval // double t = 0; // double rtcp_min_time = RTCP_MinTime; // // // Number of member for computation // unsigned int n; // int tmpSize; // // // Random number // double randNum; // // // Very first call at application start-up uses half the min delay for // // quicker notification while still allowing some time before reporting // // for randomization and to learn about other sources so the report // // interval will converge to the correct interval more quickly. The // // average RTCP size is initialized to 128 octects which is conservative. // // It assumes everyone else is generating SRs instead of RRs: // // 20 IP + 8 UDP + 52 SR + 48 SDES CNAME // if (initial) // { // rtcp_min_time /= 2; // *avgRtcpSize = 128; // } // // // If there were active senders, give them at least a minimum share of the // // RTCP bandwidth. Otherwise all participants share the RTCP Bw equally. // n = members; // if (senders > 0 && (senders < (members * RTCP_SenderBwFraction))) // { // if (weSent) // { // rtcpBw *= RTCP_SenderBwFraction; // n = senders; // } // else // { // rtcpBw *= RTCP_RcvrBwFraction; // n -= senders; // } // } // // // Update the average size estimate by the size of the report packet we // // just sent out. // tmpSize = packetSize - *avgRtcpSize; // tmpSize = (int)(tmpSize * RTCP_sizeGain); // *avgRtcpSize += tmpSize; // // // The effective number of sites times the average packet size is the // // total number of octets sent when each site sends a report. Dividing // // this by the effective bandwidth gives the time interval over which // // those packets must be sent in order to meet the bandwidth target, // // with a minimum enforced. In that time interval we send one report so // // this time is also our average time between reports. // t = (*avgRtcpSize) * n / rtcpBw; // // if (t < rtcp_min_time) // t = rtcp_min_time; // // // To avoid traffic burst from unintended synchronization with other sites // // we then pick our actual next report interval as a random number // // uniformely distributed between 0.5*t and 1.5*t. // // // Get a random number between 0 and 1 // // rand() gives a number between 0-32767. // randNum = RRCMrand() % 32767; // randNum /= 32767.0; // // // return timeout in msec // return (t * (randNum + 0.5) * 1000); #else // Minimum time between RTCP packets from this site in Msec. This time // prevents the reports from clumping when sessions are small and the law // of large numbers isn't helping to smooth out the traffic. It also keeps // the report intervals from becoming ridiculously small during transient // outages like a network partition. int RTCP_MinTime = 5000; // Interval int t = 0; int rtcp_min_time = RTCP_MinTime; // Number of member for computation unsigned int n; int tmpSize; // Random number int randNum; // Very first call at application start-up uses half the min delay for // quicker notification while still allowing some time before reporting // for randomization and to learn about other sources so the report // interval will converge to the correct interval more quickly. The // average RTCP size is initialized to 128 octects which is conservative. // It assumes everyone else is generating SRs instead of RRs: // 20 IP + 8 UDP + 52 SR + 48 SDES CNAME if (initial) { rtcp_min_time /= 2; *avgRtcpSize = 128; } // If there were active senders, give them at least a minimum share of the // RTCP bandwidth. Otherwise all participants share the RTCP Bw equally. n = members; // Only a quart of the bandwidth (=> /4). Check above with floatting point if (senders > 0 && (senders < (members / 4))) { if (weSent) { // Only a quart of the bandwidth for the sender rtcpBw /= 4; n = senders; } else { // 3/4 of the bandwidth for the receiver rtcpBw = (3*rtcpBw)/4; n -= senders; } } // Update the average size estimate by the size of the report packet we // just sent out. tmpSize = packetSize - *avgRtcpSize; tmpSize = (tmpSize+8) / 16; *avgRtcpSize += tmpSize; // The effective number of sites times the average packet size is the // total number of octets sent when each site sends a report. Dividing // this by the effective bandwidth gives the time interval over which // those packets must be sent in order to meet the bandwidth target, // with a minimum enforced. In that time interval we send one report so // this time is also our average time between reports. if (rtcpBw) t = (*avgRtcpSize) * n / rtcpBw; if (t < rtcp_min_time) t = rtcp_min_time; // To avoid traffic burst from unintended synchronization with other sites // we then pick our actual next report interval as a random number // uniformely distributed between 0.5*t and 1.5*t. // Get a random number between 0 and 1 // In order to avoid floating point operation, get a number between // 0 and 1000, i.e. converted in Msec already. Add 500 Msec instead of // 0.5 to the random number randNum = RRCMrand() % 1000; return ((t * (randNum + 500))/1000); #endif } // [EOF]