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

📄 rtp.c

📁 网络MPEG4IP流媒体开发源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	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) s = "ARANDOMSTRINGSOWEDONTCOREDUMP";        if (seed == 0) {                pid_t p = getpid();		int32_t i, n;                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);	}}/* 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 callback,                     uint8_t *userdata){	return rtp_init_if(addr, NULL, rx_port, tx_port, ttl, rtcp_bw, callback, userdata, 0);}struct rtp *rtp_init_xmitter (const char *addr, 			      uint16_t rx_port, uint16_t tx_port,			      int ttl, double rtcp_bw, 			      rtp_callback callback, 			      uint8_t *userdata){  struct rtp *session = rtp_init(addr, rx_port, tx_port, ttl, rtcp_bw,			callback, userdata);  gettimeofday(&(session->next_rtcp_send_time), NULL);  return session;}static int rtcp_local_send (struct rtp *session, uint8_t *buffer, int buflen){  return (session->rtcp_send_packet)(session->userdata, buffer, buflen);}static int rtcp_udp_send (struct rtp *session, uint8_t *buffer, int buflen){  return (udp_send(session->rtcp_socket, buffer, buflen));}struct rtp *rtp_init_extern_net (const char *addr, 				 uint16_t rx_port, uint16_t tx_port, 				 int ttl, double rtcp_bw, 				 rtp_callback callback,				 rtcp_send_packet_t rtcp_send_packet,				 uint8_t *userdata){  rtp_t rtp_ptr = rtp_init_if(addr, NULL, rx_port, tx_port, ttl, rtcp_bw, callback, userdata, 1);  if (rtp_ptr == NULL) return NULL;  rtp_ptr->rtcp_send = rtcp_local_send;  rtp_ptr->rtcp_send_packet = rtcp_send_packet;  return (rtp_ptr);}/** * 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 callback,                        uint8_t *userdata,			int dont_init_sockets){	struct rtp 	*session;	int         	 i, j;	char		*cname;	char *hname;        if (ttl < 0) {                rtp_message(LOG_CRIT, "ttl must be greater than zero");                return NULL;        }        if (rx_port % 2) {                rtp_message(LOG_CRIT, "rx_port must be even");                return NULL;        }        if (tx_port % 2) {                rtp_message(LOG_CRIT, "tx_port must be even");                return NULL;        }	session 		= (struct rtp *) xmalloc(sizeof(struct rtp));	session->magic		= 0xfeedface;	session->opt		= (options *) xmalloc(sizeof(options));	session->userdata	= userdata;	session->addr		= xstrdup(addr);	session->rx_port	= rx_port;	session->tx_port	= tx_port;	session->ttl		= min(ttl, 127);	init_opt(session);	if (dont_init_sockets == 0) {	  session->rtp_socket	= udp_init_if(addr, iface, rx_port, tx_port, ttl);	  session->rtcp_socket = udp_init_if(addr, iface, (uint16_t) (rx_port ? rx_port + 1 : 0), (uint16_t) (tx_port + 1), ttl);	  if (session->rtp_socket == NULL || session->rtcp_socket == NULL) {	    xfree(session);	    return NULL;	  }	} else {	  session->rtp_socket = NULL;	  session->rtcp_socket = NULL;	}	hname = udp_host_addr(session->rtp_socket);        init_rng(hname);	if (hname != NULL) {	  xfree(hname);	}	session->my_ssrc            = (uint32_t) lrand48();	session->rtcp_send          = rtcp_udp_send;	session->callback           = 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            = rtcp_bw;	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->encryption_enabled = 0;	session->encryption_algorithm = NULL;	/* Calculate when we're supposed to send our first RTCP packet... */	tv_add(&(session->next_rtcp_send_time), rtcp_interval(session));	/* Initialise the source database... */	for (i = 0; i < RTP_DB_SIZE; i++) {		session->db[i] = NULL;	}	session->last_advertised_csrc = 0;        /* Initialize sentinels in rr table */        for (i = 0; i < RTP_DB_SIZE; i++) {                for (j = 0; j < RTP_DB_SIZE; j++) {                        session->rr[i][j].next = &session->rr[i][j];                        session->rr[i][j].prev = &session->rr[i][j];                }        }	/* Create a database entry for ourselves... */	create_source(session, session->my_ssrc, FALSE);	cname = get_cname(session->rtp_socket);	rtp_set_sdes(session, session->my_ssrc, RTCP_SDES_CNAME, cname, strlen(cname));	xfree(cname);	/* cname is copied by rtp_set_sdes()... */	return session;}/** * rtp_set_my_ssrc: * @session: the RTP session  * @ssrc: the SSRC to be used by the RTP session *  * This function coerces the local SSRC identifer to be ssrc.  For * this function to succeed it must be called immediately after * rtp_init or rtp_init_if.  The intended purpose of this * function is to co-ordinate SSRC's between layered sessions, it * should not be used otherwise. * * Returns: TRUE on success, FALSE otherwise.   */int rtp_set_my_ssrc(struct rtp *session, uint32_t ssrc){        source *s;        uint32_t h;        if (session->ssrc_count != 1 && session->sender_count != 0) {                return FALSE;        }        /* Remove existing source */        h = ssrc_hash(session->my_ssrc);        s = session->db[h];        session->db[h] = NULL;        /* Fill in new ssrc       */        session->my_ssrc = ssrc;        s->ssrc          = ssrc;        h                = ssrc_hash(ssrc);        /* Put source back        */

⌨️ 快捷键说明

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