MythTV  0.26-pre
rtcp_from_spec.c
Go to the documentation of this file.
00001 /* RTCP code taken directly from the most recent RTP specification:
00002  *     draft-ietf-avt-rtp-new-11.txt
00003  * Implementation
00004  */
00005 
00006 #include "rtcp_from_spec.h"
00007 
00008 /*****
00009 
00010 A.7 Computing the RTCP Transmission Interval
00011 
00012    The following functions implement the RTCP transmission and reception
00013    rules described in Section 6.2. These rules are coded in several
00014    functions:
00015 
00016        o  rtcp_interval() computes the deterministic calculated
00017           interval, measured in seconds.  The parameters are defined in
00018           Section 6.3.
00019 
00020        o  OnExpire() is called when the RTCP transmission timer expires.
00021 
00022        o  OnReceive() is called whenever an RTCP packet is received.
00023 
00024    Both OnExpire() and OnReceive() have event e as an argument. This is
00025    the next scheduled event for that participant, either an RTCP report
00026    or a BYE packet.  It is assumed that the following functions are
00027    available:
00028 
00029        o  Schedule(time t, event e) schedules an event e to occur at
00030           time t. When time t arrives, the function OnExpire is called
00031           with e as an argument.
00032 
00033        o  Reschedule(time t, event e) reschedules a previously scheduled
00034           event e for time t.
00035 
00036        o  SendRTCPReport(event e) sends an RTCP report.
00037 
00038        o  SendBYEPacket(event e) sends a BYE packet.
00039 
00040        o  TypeOfEvent(event e) returns EVENT_BYE if the event being
00041           processed is for a BYE packet to be sent, else it returns
00042           EVENT_REPORT.
00043 
00044        o  PacketType(p) returns PACKET_RTCP_REPORT if packet p is an
00045           RTCP report (not BYE), PACKET_BYE if its a BYE RTCP packet,
00046           and PACKET_RTP if its a regular RTP data packet.
00047 
00048        o  ReceivedPacketSize() and SentPacketSize() return the size of
00049           the referenced packet in octets.
00050 
00051        o  NewMember(p) returns a 1 if the participant who sent packet p
00052           is not currently in the member list, 0 otherwise. Note this
00053           function is not sufficient for a complete implementation
00054           because each CSRC identifier in an RTP packet and each SSRC in
00055           a BYE packet should be processed.
00056 
00057        o  NewSender(p) returns a 1 if the participant who sent packet p
00058           is not currently in the sender sublist of the member list, 0
00059           otherwise.
00060 
00061        o  AddMember() and RemoveMember() to add and remove participants
00062           from the member list.
00063 
00064        o  AddSender() and RemoveSender() to add and remove participants
00065           from the sender sublist of the member list.
00066 *****/
00067 
00068 
00069    double rtcp_interval(int members,
00070                         int senders,
00071                         double rtcp_bw,
00072                         int we_sent,
00073                         double avg_rtcp_size,
00074                         int initial)
00075    {
00076        /*
00077         * Minimum average time between RTCP packets from this site (in
00078         * seconds).  This time prevents the reports from `clumping' when
00079         * sessions are small and the law of large numbers isn't helping
00080         * to smooth out the traffic.  It also keeps the report interval
00081         * from becoming ridiculously small during transient outages like
00082         * a network partition.
00083         */
00084        double const RTCP_MIN_TIME = 5.;
00085        /*
00086         * Fraction of the RTCP bandwidth to be shared among active
00087         * senders.  (This fraction was chosen so that in a typical
00088         * session with one or two active senders, the computed report
00089         * time would be roughly equal to the minimum report time so that
00090         * we don't unnecessarily slow down receiver reports.) The
00091         * receiver fraction must be 1 - the sender fraction.
00092         */
00093        double const RTCP_SENDER_BW_FRACTION = 0.25;
00094        double const RTCP_RCVR_BW_FRACTION = (1-RTCP_SENDER_BW_FRACTION);
00095        /*
00096         * To compensate for "unconditional reconsideration" converging to a
00097         * value below the intended average.
00098         */
00099        double const COMPENSATION = 2.71828 - 1.5;
00100 
00101        double t;                   /* interval */
00102        double rtcp_min_time = RTCP_MIN_TIME;
00103        int n;                      /* no. of members for computation */
00104 
00105        /*
00106         * Very first call at application start-up uses half the min
00107         * delay for quicker notification while still allowing some time
00108         * before reporting for randomization and to learn about other
00109         * sources so the report interval will converge to the correct
00110         * interval more quickly.
00111         */
00112        if (initial) {
00113            rtcp_min_time /= 2;
00114        }
00115 
00116        /*
00117         * If there were active senders, give them at least a minimum
00118         * share of the RTCP bandwidth.  Otherwise all participants share
00119         * the RTCP bandwidth equally.
00120         */
00121        n = members;
00122        if (senders > 0 && senders < members * RTCP_SENDER_BW_FRACTION) {
00123            if (we_sent) {
00124                rtcp_bw *= RTCP_SENDER_BW_FRACTION;
00125                n = senders;
00126            } else {
00127                rtcp_bw *= RTCP_RCVR_BW_FRACTION;
00128                n -= senders;
00129            }
00130        }
00131 
00132        /*
00133         * The effective number of sites times the average packet size is
00134         * the total number of octets sent when each site sends a report.
00135         * Dividing this by the effective bandwidth gives the time
00136         * interval over which those packets must be sent in order to
00137         * meet the bandwidth target, with a minimum enforced.  In that
00138         * time interval we send one report so this time is also our
00139         * average time between reports.
00140         */
00141        t = avg_rtcp_size * n / rtcp_bw;
00142        if (t < rtcp_min_time) t = rtcp_min_time;
00143 
00144        /*
00145         * To avoid traffic bursts from unintended synchronization with
00146         * other sites, we then pick our actual next report interval as a
00147         * random number uniformly distributed between 0.5*t and 1.5*t.
00148         */
00149        t = t * (drand48() + 0.5);
00150        t = t / COMPENSATION;
00151        return t;
00152    }
00153 
00154    void OnExpire(event e,
00155                  int    members,
00156                  int    senders,
00157                  double rtcp_bw,
00158                  int    we_sent,
00159                  double *avg_rtcp_size,
00160                  int    *initial,
00161                  time_tp   tc,
00162                  time_tp   *tp,
00163                  int    *pmembers)
00164    {
00165        /* This function is responsible for deciding whether to send
00166         * an RTCP report or BYE packet now, or to reschedule transmission.
00167         * It is also responsible for updating the pmembers, initial, tp,
00168         * and avg_rtcp_size state variables. This function should be called
00169         * upon expiration of the event timer used by Schedule(). */
00170 
00171        double t;     /* Interval */
00172        double tn;    /* Next transmit time */
00173 
00174        /* In the case of a BYE, we use "unconditional reconsideration" to
00175         * reschedule the transmission of the BYE if necessary */
00176 
00177        if (TypeOfEvent(e) == EVENT_BYE) {
00178            t = rtcp_interval(members,
00179                              senders,
00180                              rtcp_bw,
00181                              we_sent,
00182                              *avg_rtcp_size,
00183                              *initial);
00184            tn = *tp + t;
00185            if (tn <= tc) {
00186                SendBYEPacket(e);
00187                exit(1);
00188            } else {
00189                Schedule(tn, e);
00190            }
00191 
00192        } else if (TypeOfEvent(e) == EVENT_REPORT) {
00193            t = rtcp_interval(members,
00194                              senders,
00195                              rtcp_bw,
00196                              we_sent,
00197                              *avg_rtcp_size,
00198                              *initial);
00199            tn = *tp + t;
00200 
00201            if (tn <= tc) {
00202                SendRTCPReport(e);
00203                *avg_rtcp_size = (1./16.)*SentPacketSize(e) +
00204                    (15./16.)*(*avg_rtcp_size);
00205                *tp = tc;
00206 
00207                /* We must redraw the interval. Don't reuse the
00208                   one computed above, since its not actually
00209                   distributed the same, as we are conditioned
00210                   on it being small enough to cause a packet to
00211                   be sent */
00212 
00213                t = rtcp_interval(members,
00214                                  senders,
00215                                  rtcp_bw,
00216                                  we_sent,
00217                                  *avg_rtcp_size,
00218                                  *initial);
00219 
00220                Schedule(t+tc,e);
00221                *initial = 0;
00222            } else {
00223                Schedule(tn, e);
00224            }
00225            *pmembers = members;
00226        }
00227    }
00228 
00229 
00230    void OnReceive(packet p,
00231                   event e,
00232                   int *members,
00233                   int *pmembers,
00234                   int *senders,
00235                   double *avg_rtcp_size,
00236                   double *tp,
00237                   double tc,
00238                   double tn)
00239    {
00240        /* What we do depends on whether we have left the group, and
00241         * are waiting to send a BYE (TypeOfEvent(e) == EVENT_BYE) or
00242         * an RTCP report. p represents the packet that was just received. */
00243 
00244        if (PacketType(p) == PACKET_RTCP_REPORT) {
00245            if (NewMember(p) && (TypeOfEvent(e) == EVENT_REPORT)) {
00246                AddMember(p);
00247                *members += 1;
00248            }
00249            *avg_rtcp_size = (1./16.)*ReceivedPacketSize(p) +
00250                (15./16.)*(*avg_rtcp_size);
00251        } else if (PacketType(p) == PACKET_RTP) {
00252            if (NewMember(p) && (TypeOfEvent(e) == EVENT_REPORT)) {
00253                AddMember(p);
00254                *members += 1;
00255            }
00256            if (NewSender(p) && (TypeOfEvent(e) == EVENT_REPORT)) {
00257                AddSender(p);
00258                *senders += 1;
00259            }
00260        } else if (PacketType(p) == PACKET_BYE) {
00261            *avg_rtcp_size = (1./16.)*ReceivedPacketSize(p) +
00262                (15./16.)*(*avg_rtcp_size);
00263 
00264            if (TypeOfEvent(e) == EVENT_REPORT) {
00265                if (NewSender(p) == FALSE) {
00266                    RemoveSender(p);
00267                    *senders -= 1;
00268                }
00269 
00270                if (NewMember(p) == FALSE) {
00271                    RemoveMember(p);
00272                    *members -= 1;
00273                }
00274 
00275                if(*members < *pmembers) {
00276                    tn = tc + (((double) *members)/(*pmembers))*(tn - tc);
00277                    *tp = tc - (((double) *members)/(*pmembers))*(tc - *tp);
00278 
00279                    /* Reschedule the next report for time tn */
00280 
00281                    Reschedule(tn, e);
00282                    *pmembers = *members;
00283                }
00284 
00285            } else if (TypeOfEvent(e) == EVENT_BYE) {
00286                *members += 1;
00287            }
00288        }
00289    }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends