RFC1889(3) RTP

A.  Algorithms

   We provide examples of C code for aspects of RTP sender and receiver
   algorithms. There may be other implementation methods that are faster
   in particular operating environments or have other advantages. These
   implementation notes are for informational purposes only and are
   meant to clarify the RTP specification.

   The following definitions are used for all examples; for clarity and
   brevity, the structure definitions are only valid for 32-bit big-
   endian (most significant octet first) architectures. Bit fields are
   assumed to be packed tightly in big-endian bit order, with no
   additional padding. Modifications would be required to construct a
   portable implementation.

   /*
    * rtp.h  --  RTP header file (RFC XXXX)
    */
   #include <sys/types.h>

   /*
    * The type definitions below are valid for 32-bit architectures and
    * may have to be adjusted for 16- or 64-bit architectures.
    */
   typedef unsigned char  u_int8;
   typedef unsigned short u_int16;
   typedef unsigned int   u_int32;
   typedef          short int16;

   /*
    * Current protocol version.
    */
   #define RTP_VERSION    2

   #define RTP_SEQ_MOD (1<<16)
   #define RTP_MAX_SDES 255      /* maximum text length for SDES */

   typedef enum {
       RTCP_SR   = 200,
       RTCP_RR   = 201,
       RTCP_SDES = 202,
       RTCP_BYE  = 203,
       RTCP_APP  = 204
   } rtcp_type_t;

   typedef enum {
       RTCP_SDES_END   = 0,
       RTCP_SDES_CNAME = 1,



Schulzrinne, et al          Standards Track                    [Page 56]

RFC 1889                          RTP                       January 1996


       RTCP_SDES_NAME  = 2,
       RTCP_SDES_EMAIL = 3,
       RTCP_SDES_PHONE = 4,
       RTCP_SDES_LOC   = 5,
       RTCP_SDES_TOOL  = 6,
       RTCP_SDES_NOTE  = 7,
       RTCP_SDES_PRIV  = 8
   } rtcp_sdes_type_t;

   /*
    * RTP data header
    */
   typedef struct {
       unsigned int version:2;   /* protocol version */
       unsigned int p:1;         /* padding flag */
       unsigned int x:1;         /* header extension flag */
       unsigned int cc:4;        /* CSRC count */
       unsigned int m:1;         /* marker bit */
       unsigned int pt:7;        /* payload type */
       u_int16 seq;              /* sequence number */
       u_int32 ts;               /* timestamp */
       u_int32 ***c;             /* synchronization source */
       u_int32 csrc[1];          /* optional CSRC list */
   } rtp_hdr_t;

   /*
    * RTCP common header word
    */
   typedef struct {
       unsigned int version:2;   /* protocol version */
       unsigned int p:1;         /* padding flag */
       unsigned int count:5;     /* varies by packet type */
       unsigned int pt:8;        /* RTCP packet type */
       u_int16 length;           /* pkt len in words, w/o this word */
   } rtcp_common_t;

   /*
    * Big-endian mask for version, padding bit and packet type pair
    */
   #define RTCP_VALID_MASK (0xc000 | 0x2000 | 0xfe)
   #define RTCP_VALID_VALUE ((RTP_VERSION << 14) | RTCP_SR)

   /*
    * Reception report block
    */
   typedef struct {
       u_int32 ***c;             /* data source being reported */
       unsigned int fraction:8;  /* fraction lost since last SR/RR */



Schulzrinne, et al          Standards Track                    [Page 57]

RFC 1889                          RTP                       January 1996


       int lost:24;              /* cumul. no. pkts lost (signed!) */
       u_int32 last_seq;         /* extended last seq. no. received */
       u_int32 jitter;           /* interarrival jitter */
       u_int32 lsr;              /* last SR packet from this source */
       u_int32 dlsr;             /* delay since last SR packet */
   } rtcp_rr_t;

   /*
    * SDES item
    */
   typedef struct {
       u_int8 type;              /* type of item (rtcp_sdes_type_t) */
       u_int8 length;            /* length of item (in octets) */
       char data[1];             /* text, not null-terminated */
   } rtcp_sdes_item_t;

   /*
    * One RTCP packet
    */
   typedef struct {
       rtcp_common_t common;     /* common header */
       union {
           /* sender report (SR) */
           struct {
               u_int32 ***c;     /* sender generating this report */
               u_int32 ntp_sec;  /* NTP timestamp */
               u_int32 ntp_frac;
               u_int32 rtp_ts;   /* RTP timestamp */
               u_int32 psent;    /* packets sent */
               u_int32 osent;    /* octets sent */
               rtcp_rr_t rr[1];  /* variable-length list */
           } sr;

           /* reception report (RR) */
           struct {
               u_int32 ***c;     /* receiver generating this report */
               rtcp_rr_t rr[1];  /* variable-length list */
           } rr;

           /* source description (SDES) */
           struct rtcp_sdes {
               u_int32 src;      /* first ***C/CSRC */
               rtcp_sdes_item_t item[1]; /* list of SDES items */
           } sdes;

           /* BYE */
           struct {
               u_int32 src[1];   /* list of sources */



Schulzrinne, et al          Standards Track                    [Page 58]

RFC 1889                          RTP                       January 1996


               /* can't express trailing text for reason */
           } bye;
       } r;
   } rtcp_t;

   typedef struct rtcp_sdes rtcp_sdes_t;

   /*
    * Per-source state information
    */
   typedef struct {
       u_int16 max_seq;        /* highest seq. number seen */
       u_int32 cycles;         /* shifted count of seq. number cycles */
       u_int32 base_seq;       /* base seq number */
       u_int32 bad_seq;        /* last 'bad' seq number + 1 */
       u_int32 probation;      /* sequ. packets till source is valid */
       u_int32 received;       /* packets received */
       u_int32 expected_prior; /* packet expected at last interval */
       u_int32 received_prior; /* packet received at last interval */
       u_int32 transit;        /* relative trans time for prev pkt */
       u_int32 jitter;         /* estimated jitter */
       /* ... */
   } source;

A.1 RTP Data Header Validity Checks

   An RTP receiver should check the validity of the RTP header on
   incoming packets since they might be encrypted or might be from a
   different application that happens to be misaddressed. Similarly, if
   encryption is enabled, the header validity check is needed to verify
   that incoming packets have been correctly decrypted, although a
   failure of the header validity check (e.g., unknown payload type) may
   not necessarily indicate decryption failure.

   Only weak validity checks are possible on an RTP data packet from a
   source that has not been heard before:

        o RTP version field must equal 2.

        o The payload type must be known, in particular it must not be
         equal to SR or RR.

        o If the P bit is set, then the last octet of the packet must
         contain a valid octet count, in particular, less than the total
         packet length minus the header size.

        o The X bit must be zero if the profile does not specify that
         the header extension mechanism may be used. Otherwise, the



Schulzrinne, et al          Standards Track                    [Page 59]

RFC 1889                          RTP                       January 1996


         extension length field must be less than the total packet size
         minus the fixed header length and padding.

        o The length of the packet must be consistent with CC and
         payload type (if payloads have a known length).

   The last three checks are somewhat complex and not always possible,
   leaving only the first two which total just a few bits. If the ***C
   identifier in the packet is one that has been received before, then
   the packet is probably valid and checking if the sequence number is
   in the expected range provides further validation. If the ***C
   identifier has not been seen before, then data packets carrying that
   identifier may be considered invalid until a small number of them
   arrive with consecutive sequence numbers.

   The routine update_seq shown below ensures that a source is declared
   valid only after MIN_SEQUENTIAL packets have been received in
   sequence. It also validates the sequence number seq of a newly
   received packet and updates the sequence state for the packet's
   source in the structure to which s points.

   When a new source is heard for the first time, that is, its ***C
   identifier is not in the table (see Section 8.2), and the per-source
   state is allocated for it, s->probation should be set to the number
   of sequential packets required before declaring a source valid
   (parameter MIN_SEQUENTIAL ) and s->max_seq initialized to seq-1 s-
   >probation marks the source as not yet valid so the state may be
   discarded after a short timeout rather than a long one, as discussed
   in Section 6.2.1.

   After a source is considered valid, the sequence number is considered
   valid if it is no more than MAX_DROPOUT ahead of s->max_seq nor more
   than MAX_MISORDER behind. If the new sequence number is ahead of
   max_seq modulo the RTP sequence number range (16 bits), but is
   smaller than max_seq , it has wrapped around and the (shifted) count
   of sequence number cycles is incremented. A value of one is returned
   to indicate a valid sequence number.

   Otherwise, the value zero is returned to indicate that the validation
   failed, and the bad sequence number is stored. If the next packet
   received carries the next higher sequence number, it is considered
   the valid start of a new packet sequence presumably caused by an
   extended dropout or a source restart. Since multiple complete
   sequence number cycles may have been missed, the packet loss
   statistics are reset.

   Typical values for the parameters are shown, based on a maximum
   misordering time of 2 seconds at 50 packets/second and a maximum



Schulzrinne, et al          Standards Track                    [Page 60]

RFC 1889                          RTP                       January 1996


   dropout of 1 minute. The dropout parameter MAX_DROPOUT should be a
   small fraction of the 16-bit sequence number space to give a
   reasonable probability that new sequence numbers after a restart will
   not fall in the acceptable range for sequence numbers from before the
   restart.

   void init_seq(source *s, u_int16 seq)
   {
       s->base_seq = seq - 1;
       s->max_seq = seq;
       s->bad_seq = RTP_SEQ_MOD + 1;
       s->cycles = 0;
       s->received = 0;
       s->received_prior = 0;
       s->expected_prior = 0;
       /* other initialization */
   }

   int update_seq(source *s, u_int16 seq)
   {
       u_int16 udelta = seq - s->max_seq;
       const int MAX_DROPOUT = 3000;
       const int MAX_MISORDER = 100;
       const int MIN_SEQUENTIAL = 2;

       /*
        * Source is not valid until MIN_SEQUENTIAL packets with
        * sequential sequence numbers have been received.
        */
       if (s->probation) {
           /* packet is in sequence */
           if (seq == s->max_seq + 1) {
               s->probation--;
               s->max_seq = seq;
               if (s->probation == 0) {
                   init_seq(s, seq);
                   s->received++;
                   return 1;
               }
           } else {
               s->probation = MIN_SEQUENTIAL - 1;
               s->max_seq = seq;
           }
           return 0;
       } else if (udelta < MAX_DROPOUT) {
           /* in order, with permissible gap */
           if (seq < s->max_seq) {
               /*



Schulzrinne, et al          Standards Track                    [Page 61]

RFC 1889                          RTP                       January 1996


                * Sequence number wrapped - count another 64K cycle.
                */
               s->cycles += RTP_SEQ_MOD;
           }
           s->max_seq = seq;
       } else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) {
           /* the sequence number made a very large jump */
           if (seq == s->bad_seq) {
               /*
                * Two sequential packets -- assume that the other side
                * restarted without telling us so just re-sync
                * (i.e., pretend this was the first packet).
                */
               init_seq(s, seq);
           }
           else {
               s->bad_seq = (seq + 1) & (RTP_SEQ_MOD-1);
               return 0;
           }
       } else {
           /* duplicate or reordered packet */
       }
       s->received++;
       return 1;
   }

   The validity check can be made stronger requiring more than two
   packets in sequence.  The disadvantages are that a larger number of
   initial packets will be discarded and that high packet loss rates
   could prevent validation. However, because the RTCP header validation
   is relatively strong, if an RTCP packet is received from a source
   before the data packets, the count could be adjusted so that only two
   packets are required in sequence.  If initial data loss for a few
   seconds can be tolerated, an application could choose to discard all
   data packets from a source until a valid RTCP packet has been
   received from that source.

   Depending on the application and encoding, algorithms may exploit
   additional knowledge about the payload format for further validation.
   For payload types where the timestamp increment is the same for all
   packets, the timestamp values can be predicted from the previous
   packet received from the same source using the sequence number
   difference (assuming no change in payload type).

   A strong "fast-path" check is possible since with high probability
   the first four octets in the header of a newly received RTP data
   packet will be just the same as that of the previous packet from the
   same ***C except that the sequence number will have increased by one.



Schulzrinne, et al          Standards Track                    [Page 62]

RFC 1889                          RTP                       January 1996


   Similarly, a single-entry cache may be used for faster ***C lookups
   in applications where data is typically received from one source at a
   time.

A.2 RTCP Header Validity Checks

   The following checks can be applied to RTCP packets.

        o RTP version field must equal 2.

        o The payload type field of the first RTCP packet in a compound
         packet must be equal to SR or RR.

        o The padding bit (P) should be zero for the first packet of a
         compound RTCP packet because only the last should possibly need
         padding.

        o The length fields of the individual RTCP packets must total to
         the overall length of the compound RTCP packet as received.
         This is a fairly strong check.

   The code fragment below performs all of these checks. The packet type
   is not checked for subsequent packets since unknown packet types may
   be present and should be ignored.

       u_int32 len;        /* length of compound RTCP packet in words */
       rtcp_t *r;          /* RTCP header */
       rtcp_t *end;        /* end of compound RTCP packet */

       if ((*(u_int16 *)r & RTCP_VALID_MASK) != RTCP_VALID_VALUE) {
           /* something wrong with packet format */
       }
       end = (rtcp_t *)((u_int32 *)r + len);

       do r = (rtcp_t *)((u_int32 *)r + r->common.length + 1);
       while (r < end && r->common.version == 2);

       if (r != end) {
           /* something wrong with packet format */
       }

A.3 Determining the Number of RTP Packets Expected and Lost

   In order to compute packet loss rates, the number of packets expected
   and actually received from each source needs to be known, using per-
   source state information defined in struct source referenced via
   pointer s in the code below. The number of packets received is simply
   the count of packets as they arrive, including any late or duplicate



Schulzrinne, et al          Standards Track                    [Page 63]

RFC 1889                          RTP                       January 1996


   packets. The number of packets expected can be computed by the
   receiver as the difference between the highest sequence number
   received ( s->max_seq ) and the first sequence number received ( s-
   >base_seq ). Since the sequence number is only 16 bits and will wrap
   around, it is necessary to extend the highest sequence number with
   the (shifted) count of sequence number wraparounds ( s->cycles ).
   Both the received packet count and the count of cycles are maintained
   the RTP header validity check routine in Appendix A.1.

       extended_max = s->cycles + s->max_seq;
       expected = extended_max - s->base_seq + 1;

   The number of packets lost is defined to be the number of packets
   expected less the number of packets actually received:

       lost = expected - s->received;

   Since this number is carried in 24 bits, it should be clamped at
   0xffffff rather than wrap around to zero.

   The fraction of packets lost during the last reporting interval
   (since the previous SR or RR packet was sent) is calculated from
   differences in the expected and received packet counts across the
   interval, where expected_prior and received_prior are the values
   saved when the previous reception report was generated:

       expected_interval = expected - s->expected_prior;
       s->expected_prior = expected;
       received_interval = s->received - s->received_prior;
       s->received_prior = s->received;
       lost_interval = expected_interval - received_interval;
       if (expected_interval == 0 || lost_interval <= 0) fraction = 0;
       else fraction = (lost_interval << 8) / expected_interval;

   The resulting fraction is an 8-bit fixed point number with the binary
   point at the left edge.

A.4 Generating SDES RTCP Packets

   This function builds one SDES chunk into buffer b composed of argc
   items supplied in arrays type , value and length b

   char *rtp_write_sdes(char *b, u_int32 src, int argc,
                        rtcp_sdes_type_t type[], char *value[],
                        int length[])
   {
       rtcp_sdes_t *s = (rtcp_sdes_t *)b;
       rtcp_sdes_item_t *rsp;



Schulzrinne, et al          Standards Track                    [Page 64]

RFC 1889                          RTP                       January 1996


       int i;
       int len;
       int pad;

       /* ***C header */
       s->src = src;
       rsp = &s->item[0];

       /* SDES items */
       for (i = 0; i < argc; i++) {
           rsp->type = type[i];
           len = length[i];
           if (len > RTP_MAX_SDES) {
               /* invalid length, may want to take other action */
               len = RTP_MAX_SDES;
           }
           rsp->length = len;
           memcpy(rsp->data, value[i], len);
           rsp = (rtcp_sdes_item_t *)&rsp->data[len];
       }

       /* terminate with end marker and pad to next 4-octet boundary */
       len = ((char *) rsp) - b;
       pad = 4 - (len & 0x3);
       b = (char *) rsp;
       while (pad--) *b++ = RTCP_SDES_END;

       return b;
   }

A.5 Parsing RTCP SDES Packets

   This function parses an SDES packet, calling functions find_member()
   to find a pointer to the information for a session member given the
   ***C identifier and member_sdes() to store the new SDES information
   for that member. This function expects a pointer to the header of the
   RTCP packet.

   void rtp_read_sdes(rtcp_t *r)
   {
       int count = r->common.count;
       rtcp_sdes_t *sd = &r->r.sdes;
       rtcp_sdes_item_t *rsp, *rspn;
       rtcp_sdes_item_t *end = (rtcp_sdes_item_t *)
                               ((u_int32 *)r + r->common.length + 1);
       source *s;

       while (--count >= 0) {



Schulzrinne, et al          Standards Track                    [Page 65]

RFC 1889                          RTP                       January 1996


           rsp = &sd->item[0];
           if (rsp >= end) break;
           s = find_member(sd->src);

           for (; rsp->type; rsp = rspn ) {
               rspn = (rtcp_sdes_item_t *)((char*)rsp+rsp->length+2);
               if (rspn >= end) {
                   rsp = rspn;
                   break;
               }
               member_sdes(s, rsp->type, rsp->data, rsp->length);
           }
           sd = (rtcp_sdes_t *)
                ((u_int32 *)sd + (((char *)rsp - (char *)sd) >> 2)+1);
       }
       if (count >= 0) {
           /* invalid packet format */
       }
   }

A.6 Generating a Random 32-bit Identifier

   The following subroutine generates a random 32-bit identifier using
   the MD5 routines published in RFC 1321 [23]. The system routines may
   not be present on all operating systems, but they should serve as
   hints as to what kinds of information may be used. Other system calls
   that may be appropriate include

        o getdomainname() ,

        o getwd() , or

        o getrusage()

   "Live" video or audio samples are also a good source of random
   numbers, but care must be taken to avoid using a turned-off
   microphone or blinded camera as a source [7].

   Use of this or similar routine is suggested to generate the initial
   seed for the random number generator producing the RTCP period (as
   shown in Appendix A.7), to generate the initial values for the
   sequence number and timestamp, and to generate ***C values.  Since
   this routine is likely to be CPU-intensive, its direct use to
   generate RTCP periods is inappropriate because predictability is not
   an issue. Note that this routine produces the same result on repeated
   calls until the value of the system clock changes unless different
   values are supplied for the type argument.




Schulzrinne, et al          Standards Track                    [Page 66]

RFC 1889                          RTP                       January 1996


   /*
    * Generate a random 32-bit quantity.
    */
   #include <sys/types.h>   /* u_long */
   #include <sys/time.h>    /* gettimeofday() */
   #include <unistd.h>      /* get..() */
   #include <stdio.h>       /* printf() */
   #include <time.h>        /* clock() */
   #include <sys/utsname.h> /* uname() */
   #include "global.h"      /* from RFC 1321 */
   #include "md5.h"         /* from RFC 1321 */

   #define MD_CTX MD5_CTX
   #define MDInit MD5Init
   #define MDUpdate MD5Update
   #define MDFinal MD5Final

   static u_long md_32(char *string, int length)
   {
       MD_CTX context;
       union {
           char   c[16];
           u_long x[4];
       } digest;
       u_long r;
       int i;

       MDInit (&context);
       MDUpdate (&context, string, length);
       MDFinal ((unsigned char *)&digest, &context);
       r = 0;
       for (i = 0; i < 3; i++) {
           r ^= digest.x[i];
       }
       return r;
   }                               /* md_32 */


   /*
    * Return random unsigned 32-bit quantity. Use 'type' argument if you
    * need to generate several different values in close succession.
    */
   u_int32 random32(int type)
   {
       struct {
           int     type;
           struct  timeval tv;
           clock_t cpu;



Schulzrinne, et al          Standards Track                    [Page 67]

RFC 1889                          RTP                       January 1996


           pid_t   pid;
           u_long  hid;
           uid_t   uid;
           gid_t   gid;
           struct  utsname name;
       } s;

       gettimeofday(&s.tv, 0);
       uname(&s.name);
       s.type = type;
       s.cpu  = clock();
       s.pid  = getpid();
       s.hid  = gethostid();
       s.uid  = getuid();
       s.gid  = getgid();

       return md_32((char *)&s, sizeof(s));
   }                               /* random32 */

A.7 Computing the RTCP Transmission Interval

   The following function returns the time between transmissions of RTCP
   packets, measured in seconds. It should be called after sending one
   compound RTCP packet to calculate the delay until the next should be
   sent. This function should also be called to calculate the delay
   before sending the first RTCP packet upon startup rather than send
   the packet immediately. This avoids any burst of RTCP packets if an
   application is started at many sites simultaneously, for example as a
   result of a session announcement.

   The parameters have the following meaning:

   rtcp_bw: The target RTCP bandwidth, i.e., the total bandwidth that
        will be used for RTCP packets by all members of this session, in
        octets per second. This should be 5% of the "session bandwidth"
        parameter supplied to the application at startup.

   senders: Number of active senders since sending last report, known
        from construction of receiver reports for this RTCP packet.
        Includes ourselves, if we also sent during this interval.

   members: The estimated number of session members, including
        ourselves. Incremented as we discover new session members from
        the receipt of RTP or RTCP packets, and decremented as session
        members leave (via RTCP BYE) or their state is timed out (30
        minutes is recommended). On the first call, this parameter
        should have the value 1.




Schulzrinne, et al          Standards Track                    [Page 68]

RFC 1889                          RTP                       January 1996


   we_sent: Flag that is true if we have sent data during the last two
        RTCP intervals. If the flag is true, the compound RTCP packet
        just sent contained an SR packet.

   packet_size: The size of the compound RTCP packet just sent, in
        octets, including the network encapsulation (e.g., 28 octets for
        UDP over IP).

   avg_rtcp_size: Pointer to estimator for compound RTCP packet size;
        initialized and updated by this function for the packet just
        sent, and also updated by an identical line of code in the RTCP
        receive routine for every RTCP packet received from other
        participants in the session.

   initial: Flag that is true for the first call upon startup to
        calculate the time until the first report should be sent.

   #include <math.h>

   double rtcp_interval(int members,
                        int senders,
                        double rtcp_bw,
                        int we_sent,
                        int packet_size,
                        int *avg_rtcp_size,
                        int initial)
   {
       /*
        * 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 interval from
        * becoming ridiculously small during transient outages like a
        * network partition.
        */
       double const RTCP_MIN_TIME = 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_SENDER_BW_FRACTION = 0.25;
       double const RTCP_RCVR_BW_FRACTION = (1-RTCP_SENDER_BW_FRACTION);
       /*
        * Gain (smoothing constant) for the low-pass filter that



Schulzrinne, et al          Standards Track                    [Page 69]

RFC 1889                          RTP                       January 1996


        * estimates the average RTCP packet size (see Cadzow reference).
        */
       double const RTCP_SIZE_GAIN = (1./16.);

       double t;                   /* interval */
       double rtcp_min_time = RTCP_MIN_TIME;
       int n;                      /* no. of members for computation */

       /*
        * 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 octets 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;
           *avg_rtcp_size = 128;
       }

       /*
        * If there were active senders, give them at least a minimum
        * share of the RTCP bandwidth.  Otherwise all participants share
        * the RTCP bandwidth equally.
        */
       n = members;
       if (senders > 0 && senders < members * RTCP_SENDER_BW_FRACTION) {
           if (we_sent) {
               rtcp_bw *= RTCP_SENDER_BW_FRACTION;
               n = senders;
           } else {
               rtcp_bw *= RTCP_RCVR_BW_FRACTION;
               n -= senders;
           }
       }

       /*
        * Update the average size estimate by the size of the report
        * packet we just sent.
        */
       *avg_rtcp_size += (packet_size - *avg_rtcp_size)*RTCP_SIZE_GAIN;

       /*
        * The effective number of sites times the average packet size is
        * the total number of octets sent when each site sends a report.



Schulzrinne, et al          Standards Track                    [Page 70]

RFC 1889                          RTP                       January 1996


        * 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 = (*avg_rtcp_size) * n / rtcp_bw;
       if (t < rtcp_min_time) t = rtcp_min_time;

       /*
        * To avoid traffic bursts from unintended synchronization with
        * other sites, we then pick our actual next report interval as a
        * random number uniformly distributed between 0.5*t and 1.5*t.
        */
       return t * (drand48() + 0.5);
   }

A.8 Estimating the Interarrival Jitter

   The code fragments below implement the algorithm given in Section
   6.3.1 for calculating an estimate of the statistical variance of the
   RTP data interarrival time to be inserted in the interarrival jitter
   field of reception reports. The inputs are r->ts , the timestamp from
   the incoming packet, and arrival , the current time in the same
   units. Here s points to state for the source; s->transit holds the
   relative transit time for the previous packet, and s->jitter holds
   the estimated jitter. The jitter field of the reception report is
   measured in timestamp units and expressed as an unsigned integer, but
   the jitter estimate is kept in a floating point. As each data packet
   arrives, the jitter estimate is updated:

       int transit = arrival - r->ts;
       int d = transit - s->transit;
       s->transit = transit;
       if (d < 0) d = -d;
       s->jitter += (1./16.) * ((double)d - s->jitter);

   When a reception report block (to which rr points) is generated for
   this member, the current jitter estimate is returned:

       rr->jitter = (u_int32) s->jitter;

   Alternatively, the jitter estimate can be kept as an integer, but
   scaled to reduce round-off error. The calculation is the same except
   for the last line:

       s->jitter += d - ((s->jitter + 8) >> 4);




Schulzrinne, et al          Standards Track                    [Page 71]

RFC 1889                          RTP                       January 1996


   In this case, the estimate is sampled for the reception report as:

       rr->jitter = s->jitter >> 4;


B.  Security Considerations

   RTP suffers from the same security liabilities as the underlying
   protocols. For example, an impostor can fake source or destination
   network addresses, or change the header or payload. Within RTCP, the
   CNAME and NAME information may be used to impersonate another
   participant. In addition, RTP may be sent via IP multicast, which
   provides no direct means for a sender to know all the receivers of
   the data sent and therefore no measure of privacy. Rightly or not,
   users may be more sensitive to privacy concerns with audio and video
   communication than they have been with more traditional forms of
   network communication [24]. Therefore, the use of security mechanisms
   with RTP is important. These mechanisms are discussed in Section 9.

   RTP-level translators or mixers may be used to allow RTP traffic to
   reach hosts behind firewalls. Appropriate firewall security
   principles and practices, which are beyond the scope of this
   document, should be followed in the design and installation of these
   devices and in the admission of RTP applications for use behind the
   firewall.

C. Authors' Addresses

   Henning Schulzrinne
   GMD Fokus
   Hardenbergplatz 2
   D-10623 Berlin
   Germany

   EMail: [email protected]


   Stephen L. Casner
   Precept Software, Inc.
   21580 Stevens Creek Boulevard, Suite 207
   Cupertino, CA 95014
   United States

   EMail: [email protected]







Schulzrinne, et al          Standards Track                    [Page 72]

RFC 1889                          RTP                       January 1996


   Ron Frederick
   Xerox Palo Alto Research Center
   3333 Coyote Hill Road
   Palo Alto, CA 94304
   United States

   EMail: [email protected]


   Van Jacobson
   MS 46a-1121
   Lawrence Berkeley National Laboratory
   Berkeley, CA 94720
   United States

   EMail: [email protected]

Acknowledgments

   This memorandum is based on discussions within the IETF Audio/Video
   Transport working group chaired by Stephen Casner. The current
   protocol has its origins in the Network Voice Protocol and the Packet
   Video Protocol (Danny Cohen and Randy Cole) and the protocol
   implemented by the vat application (Van Jacobson and Steve McCanne).
   Christian Huitema provided ideas for the random identifier generator.

D.  Bibliography

   [1] D. D. Clark and D. L. Tennenhouse, "Architectural considerations
       for a new generation of protocols," in SIGCOMM Symposium on
       Communications Architectures and Protocols , (Philadelphia,
       Pennsylvania), pp. 200--208, IEEE, Sept. 1990.  Computer
       Communications Review, Vol. 20(4), Sept. 1990.

   [2] H. Schulzrinne, "Issues in designing a transport protocol for
       audio and video conferences and other multiparticipant real-time
       applications", Work in Progress.

   [3] D. E. Comer, Internetworking with TCP/IP , vol. 1.  Englewood
       Cliffs, New Jersey: Prentice Hall, 1991.

   [4] Postel, J., "Internet Protocol", STD 5, RFC 791, USC/Information
       Sciences Institute, September 1981.

   [5] Mills, D., "Network Time Protocol Version 3", RFC 1305, UDEL,
       March 1992.





Schulzrinne, et al          Standards Track                    [Page 73]

RFC 1889                          RTP                       January 1996


   [6] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC 1700,
       USC/Information Sciences Institute, October 1994.

   [7] Eastlake, D., Crocker, S., and J. Schiller, "Randomness
       Recommendations for Security", RFC 1750, DEC, Cybercash, MIT,
       December 1994.

   [8] J.-C. Bolot, T. Turletti, and I. Wakeman, "Scalable feedback
       control for multicast video distribution in the internet," in
       SIGCOMM Symposium on Communications Architectures and Protocols ,
       (London, England), pp. 58--67, ACM, Aug. 1994.

   [9] I. Busse, B. Deffner, and H. Schulzrinne, "Dynamic QoS control of
       multimedia applications based on RTP," Computer Communications ,
       Jan.  1996.

  [10] S. Floyd and V. Jacobson, "The synchronization of periodic
       routing messages," in SIGCOMM Symposium on Communications
       Architectures and Protocols (D. P. Sidhu, ed.), (San Francisco,
       California), pp. 33--44, ACM, Sept. 1993.  also in [25].

  [11] J. A. Cadzow, Foundations of digital signal processing and data
       analysis New York, New York: Macmillan, 1987.

  [12] International Standards Organization, "ISO/IEC DIS 10646-1:1993
       information technology -- universal multiple-octet coded
       character set (UCS) -- part I: Architecture and basic
       multilingual plane," 1993.

  [13] The Unicode Consortium, The Unicode Standard New York, New York:
       Addison-Wesley, 1991.

  [14] Mockapetris, P., "Domain Names - Concepts and Facilities", STD
       13, RFC 1034, USC/Information Sciences Institute, November 1987.

  [15] Mockapetris, P., "Domain Names - Implementation and
       Specification", STD 13, RFC 1035, USC/Information Sciences
       Institute, November 1987.

  [16] Braden, R., "Requirements for Internet Hosts - Application and
       Support", STD 3, RFC 1123, Internet Engineering Task Force,
       October 1989.

  [17] Rekhter, Y., Moskowitz, R., Karrenberg, D., and G. de Groot,
       "Address Allocation for Private Internets", RFC 1597, T.J. Watson
       Research Center, IBM Corp., Chrysler Corp., RIPE NCC, March 1994.





Schulzrinne, et al          Standards Track                    [Page 74]

RFC 1889                          RTP                       January 1996


  [18] Lear, E., Fair, E., Crocker, D., and T. Kessler, "Network 10
       Considered Harmful (Some Practices Shouldn't be Codified)", RFC
       1627, Silicon Graphics, Inc., Apple Computer, Inc., Silicon
       Graphics, Inc., July 1994.

  [19] Crocker, D., "Standard for the Format of ARPA Internet Text
       Messages", STD 11, RFC 822, UDEL, August 1982.

  [20] W. Feller, An Introduction to Probability Theory and its
       Applications, Volume 1 , vol. 1.  New York, New York: John Wiley
       and Sons, third ed., 1968.

  [21] Balenson, D., "Privacy Enhancement for Internet Electronic Mail:
       Part III: Algorithms, Modes, and Identifiers", RFC 1423, TIS, IAB
       IRTF PSRG, IETF PEM WG, February 1993.

  [22] V. L. Voydock and S. T. Kent, "Security mechanisms in high-level
       network protocols," ACM Computing Surveys , vol. 15, pp. 135--
       171, June 1983.

  [23] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, MIT
       Laboratory for Computer Science and RSA Data Security, Inc.,
       April 1992.

  [24] S. Stubblebine, "Security services for multimedia conferencing,"
       in 16th National Computer Security Conference , (Baltimore,
       Maryland), pp. 391--395, Sept. 1993.

  [25] S. Floyd and V. Jacobson, "The synchronization of periodic
       routing messages," IEEE/ACM Transactions on Networking , vol. 2,
       pp.  122-136, April 1994.




















Schulzrinne, et al          Standards Track                    [Page 75]


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章