⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtp.c

📁 完整的RTP RTSP代码库
💻 C
📖 第 1 页 / 共 5 页
字号:
       * 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;}static double rtcp_interval(struct rtp *session){  /* Minimum average 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.0;  /* 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);  /* To compensate for "unconditional reconsideration" converging   */  /* to a value below the intended average.                         */  double const COMPENSATION            = 2.71828 - 1.5;  double t;				              /* interval */  double rtcp_min_time = RTCP_MIN_TIME;  int n;			        /* no. of members for computation */  double rtcp_bw = session->rtcp_bw;  /* 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.                                         */  if (session->initial_rtcp) {    rtcp_min_time /= 2;  }  /* If there were active senders, give them at least a minimum     */  /* share of the RTCP bandwidth.  Otherwise all participants share */  /* the RTCP bandwidth equally.                                    */  if (session->sending_bye) {    n = session->bye_count;  } else {    n = session->ssrc_count;  }  if (session->sender_count > 0 && session->sender_count < n * RTCP_SENDER_BW_FRACTION) {    if (session->we_sent) {      rtcp_bw *= RTCP_SENDER_BW_FRACTION;      n = session->sender_count;    } else {      rtcp_bw *= RTCP_RCVR_BW_FRACTION;      n -= session->sender_count;    }  }  /* 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 = session->avg_rtcp_size * n / rtcp_bw;  if (t < rtcp_min_time) {    t = rtcp_min_time;  }  session->rtcp_interval = t;  /* 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)) / COMPENSATION;}#define MAXCNAMELEN	255static char *get_cname(socket_udp *s){  /* Set the CNAME. This is "user@hostname" or just "hostname" if the username cannot be found. */  char              *hname;  char                    *uname;  char                    *cname;#ifndef WIN32  struct passwd           *pwent;#else  char *name;  int   namelen;#endif  cname = (char *) xmalloc(MAXCNAMELEN + 1);  cname[0] = '\0';  /* First, fill in the username... */#ifdef WIN32  name = NULL;  namelen = 0;  GetUserName(NULL, &namelen);  if (namelen > 0) {    name = (char*)xmalloc(namelen+1);    GetUserName(name, &namelen);  } else {    uname = getenv("USER");    if (uname != NULL) {      name = xstrdup(uname);    }  }  if (name != NULL) {    strncpy(cname, name, MAXCNAMELEN - 1);    strcat(cname, "@");    xfree(name);  }#else  pwent = getpwuid(getuid());  uname = pwent->pw_name;  if (uname != NULL) {    strncpy(cname, uname, MAXCNAMELEN - 1);    strcat(cname, "@");  }#endif          /* Now the hostname. Must be dotted-quad IP address. */  hname = udp_host_addr(s);  if (hname == NULL) {    /* If we can't get our IP address we use the loopback address... */    /* This is horrible, but it stops the code from failing.         */    strncpy(cname + strlen(cname),	    "127.0.0.1",	    MAXCNAMELEN - strlen(cname));  } else {    strncpy(cname + strlen(cname), hname, MAXCNAMELEN - strlen(cname));    xfree(hname);  }  return cname;}static void init_opt(struct rtp *session){  /* Default option settings. */  rtp_set_option(session, RTP_OPT_PROMISC,           FALSE);  rtp_set_option(session, RTP_OPT_WEAK_VALIDATION,   TRUE);  rtp_set_option(session, RTP_OPT_FILTER_MY_PACKETS, FALSE);}static void init_rng(const char *s){  static uint32_t seed;  if (s == NULL) {    /* This should never happen, but just in case */    s = "ARANDOMSTRINGSOWEDONTCOREDUMP";  }  if (seed == 0) {    pid_t p = getpid();    int32_t i = 0, n = 0;    while (*s) {      seed += (uint32_t)*s++;      seed = seed * 31 + 1;    }    seed = 1 + seed * 31 + (uint32_t)p;    srand48(seed);    /* At time of writing we use srand48 -> srand on Win32       which is only 16 bit. lrand48 -> rand which is only       15 bits, step a long way through table seq */#ifdef WIN32    n = (seed >> 16) & 0xffff;    for(i = 0; i < n; i++) {      seed = lrand48();    }#endif /* WIN32 */    UNUSED(i);    UNUSED(n);  }}rtp_stream_params_t *rtp_default_params (rtp_stream_params_t *ptr){  if (ptr == NULL) {    ptr = (rtp_stream_params_t *)malloc(sizeof(rtp_stream_params_t));  }  memset(ptr, 0, sizeof(*ptr));  ptr->rtp_socket = NULL;  ptr->rtcp_socket = NULL;     return ptr;}/* See rtp_init_if(); calling rtp_init() is just like calling * rtp_init_if() with a NULL interface argument. *//** * rtp_init: * @addr: IP destination of this session (unicast or multicast), * as an ASCII string.  May be a host name, which will be looked up, * or may be an IPv4 dotted quad or IPv6 literal adddress. * @rx_port: The port to which to bind the UDP socket * @tx_port: The port to which to send UDP packets * @ttl: The TTL with which to send multicasts * @rtcp_bw: The total bandwidth (in units of bytes per second) that is * allocated to RTCP. * @callback: See section on #rtp_callback. * @userdata: Opaque data associated with the session.  See * rtp_get_userdata(). * * * Returns: An opaque session identifier to be used in future calls to * the RTP library functions, or NULL on failure. */struct rtp *rtp_init(const char *addr, 		     uint16_t rx_port, uint16_t tx_port, 		     int ttl, double rtcp_bw,                      rtp_callback_f callback,                     void *userdata){  rtp_stream_params_t rsp;  rtp_default_params(&rsp);    rsp.rtp_addr = addr;  rsp.rtp_rx_port = rx_port;  rsp.rtp_tx_port = tx_port;  rsp.rtp_ttl = ttl;  rsp.rtcp_bandwidth = rtcp_bw;  rsp.rtp_callback = callback;  rsp.recv_userdata = userdata;    return rtp_init_stream(&rsp);}#if 0// not used any more - use rtp_init_stream with transmit_initial_rtcp = 1struct rtp *rtp_init_xmitter (const char *addr, 			      uint16_t rx_port, uint16_t tx_port,			      int ttl, double rtcp_bw, 			      rtp_callback_f callback, 			      void *userdata){  rtp_stream_params_t rsp;  rtp_default_params(&rsp);    rsp.rtp_addr = addr;  rsp.rtp_rx_port = rx_port;  rsp.rtp_tx_port = tx_port;  rsp.rtp_ttl = ttl;  rsp.rtcp_bandwidth = rtcp_bw;  rsp.rtp_callback = callback;  rsp.recv_userdata = userdata;  rsp.transmit_initial_rtcp = 1;  return rtp_init_stream(&rsp);}#endif/** * rtp_init_if: * @addr: IP destination of this session (unicast or multicast), * as an ASCII string.  May be a host name, which will be looked up, * or may be an IPv4 dotted quad or IPv6 literal adddress. * @iface: If the destination of the session is multicast, * the optional interface to bind to.  May be NULL, in which case * the default multicast interface as determined by the system * will be used. * @rx_port: The port to which to bind the UDP socket * @tx_port: The port to which to send UDP packets * @ttl: The TTL with which to send multicasts * @rtcp_bw: The total bandwidth (in units of ___) that is * allocated to RTCP. * @callback: See section on #rtp_callback. * @userdata: Opaque data associated with the session.  See * rtp_get_userdata(). * * Creates and initializes an RTP session. * * Returns: An opaque session identifier to be used in future calls to * the RTP library functions, or NULL on failure. */struct rtp *rtp_init_if(const char *addr, char *iface, 			uint16_t rx_port, uint16_t tx_port, 			int ttl, double rtcp_bw,                         rtp_callback_f callback,                        void *userdata,			int dont_init_sockets){  rtp_stream_params_t rsp;  rtp_default_params(&rsp);  rsp.physical_interface_addr = iface;  rsp.rtp_addr = addr;  rsp.rtp_tx_port = tx_port;  rsp.rtp_rx_port = rx_port;  rsp.rtp_ttl = ttl;  rsp.rtcp_bandwidth = rtcp_bw;  rsp.rtp_callback = callback;  rsp.recv_userdata = userdata;  rsp.dont_init_sockets = dont_init_sockets;  return rtp_init_stream(&rsp);}rtp_t rtp_init_stream (rtp_stream_params_t *rsp){  struct rtp 	*session;  int         	 i, j;  char		*cname;  char *hname;  session 		= (struct rtp *) xmalloc(sizeof(struct rtp));  memset(session, 0, sizeof(*session));  session->magic		= 0xfeedface;  session->opt		= (options *) xmalloc(sizeof(options));  session->recv_userdata	= rsp->recv_userdata;  session->send_userdata = rsp->send_userdata != NULL ? rsp->send_userdata : rsp->recv_userdata;  session->addr		= rsp->rtp_addr != NULL ? xstrdup(rsp->rtp_addr) : NULL;  session->rx_port	= rsp->rtp_rx_port;  session->tx_port	= rsp->rtp_tx_port;  session->ttl		= min(rsp->rtp_ttl, 127);  init_opt(session);  if (rsp->dont_init_sockets == 0) {    session->udp_session = udp_init_for_session();    session->rtp_socket	= udp_init_if(rsp->rtp_addr, 				      rsp->physical_interface_addr, 				      rsp->rtp_rx_port, 				      rsp->rtp_tx_port, 				      rsp->rtp_ttl);    if (rsp->rtcp_addr == NULL) rsp->rtcp_addr = rsp->rtp_addr;    if (rsp->rtcp_rx_port == 0) {      rsp->rtcp_rx_port = rsp->rtp_rx_port ? rsp->rtp_rx_port + 1 : 0;    }    if (rsp->rtcp_tx_port == 0) {      rsp->rtcp_tx_port = rsp->rtp_tx_port + 1;    }    if (rsp->rtcp_ttl == 0) rsp->rtcp_ttl = rsp->rtp_ttl;    session->rtcp_socket = udp_init_if(rsp->rtcp_addr, 				       rsp->physical_interface_addr, 				       rsp->rtcp_rx_port,				       rsp->rtcp_tx_port, 				       rsp->rtcp_ttl);    if (session->udp_session == NULL || 	session->rtp_socket == NULL || session->rtcp_socket == NULL) {      xfree(session);      return NULL;    }    session->free_sockets = 1;  } else {    session->free_sockets = 0;    session->rtp_socket = rsp->rtp_socket;    session->rtcp_socket = rsp->rtcp_socket;  }  hname = udp_host_addr(session->rtp_socket);  init_rng(hname);  if (hname != NULL) {    xfree(hname);  }  session->my_ssrc            = (uint32_t) lrand48();  session->rtcp_send_packet   = rsp->rtcp_send_packet;  session->rtp_send_packet    = rsp->rtp_send_packet;#ifdef HAVE_STRUCT_IOVEC  session->rtp_send_packet_iov= rsp->rtp_send_packet_iov;#endif  if (rsp->rtp_callback == NULL) {    session->callback = local_callback;  } else {    session->callback           = rsp->rtp_callback;  }  session->invalid_rtp_count  = 0;  session->invalid_rtcp_count = 0;  session->bye_count          = 0;  session->csrc_count         = 0;  session->ssrc_count         = 0;  session->ssrc_count_prev    = 0;  session->sender_count       = 0;  session->initial_rtcp       = TRUE;  session->sending_bye        = FALSE;  session->avg_rtcp_size      = -1;	/* Sentinal value: reception of first packet starts initial value... */  session->we_sent            = FALSE;  session->rtcp_bw            = rsp->rtcp_bandwidth;  session->sdes_count_pri     = 0;  session->sdes_count_sec     = 0;  session->sdes_count_ter     = 0;  session->rtp_seq            = (uint16_t) lrand48();  session->rtp_pcount         = 0;  session->rtp_bcount         = 0;  gettimeofday(&(session->last_update), NULL);  gettimeofday(&(session->last_rtcp_send_time), NULL);  gettimeofday(&(session->next_rtcp_send_time), NULL);  session->rtp_encryption_enabled = 0;  session->rtcp_encryption_enabled = 0;  session->encryption_algorithm = NULL;  session->mutex = MutexCreate();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -