|
MythTV
0.26-pre
|
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 }
1.7.6.1