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

📄 rtp.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* 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. */        const 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.         */		hname = "127.0.0.1";	}        strncpy(cname + strlen(cname), hname, MAXCNAMELEN - strlen(cname));        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,   FALSE);	rtp_set_option(session, RTP_OPT_FILTER_MY_PACKETS, FALSE);	rtp_set_option(session, RTP_OPT_REUSE_PACKET_BUFS, 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, 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);}/** * 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){	struct rtp 	*session;	int         	 i, j;	char		*cname;        if (ttl < 0) {                debug_msg("ttl must be greater than zero\n");                return NULL;        }        if (rx_port % 2) {                debug_msg("rx_port must be even\n");                return NULL;        }        if (tx_port % 2) {                debug_msg("tx_port must be even\n");                return NULL;        }	session 		= (struct rtp *) xmalloc(sizeof(struct rtp));	memset (session, 0, 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);	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+1), (uint16_t) (tx_port+1), ttl);	init_opt(session);	if (session->rtp_socket == NULL || session->rtcp_socket == NULL) {		xfree(session);		return NULL;	}        init_rng(udp_host_addr(session->rtp_socket));	session->my_ssrc            = (uint32_t) lrand48();	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        */        session->db[h]   = s;        return TRUE;}/** * rtp_set_option: * @session: The RTP session. * @optname: The option name, see #rtp_option. * @optval: The value to set. * * Sets the value of a session option.  See #rtp_option for * documentation on the options and their legal values. * * Returns: TRUE on success, else FALSE. */int rtp_set_option(struct rtp *session, rtp_option optname, int optval){	assert((optval == TRUE) || (optval == FALSE));	switch (optname) {		case RTP_OPT_WEAK_VALIDATION:			session->opt->wait_for_rtcp = optval;			break;	        case RTP_OPT_PROMISC:			session->opt->promiscuous_mode = optval;			break;	        case RTP_OPT_FILTER_MY_PACKETS:			session->opt->filter_my_packets = optval;			break;		case RTP_OPT_REUSE_PACKET_BUFS:			session->opt->reuse_bufs = optval;			break;        	default:			debug_msg("Ignoring unknown option (%d) in call to rtp_set_option().\n", optname);                        return FALSE;	}        return TRUE;}/** * rtp_get_option: * @session: The RTP session. * @optname: The option name, see #rtp_option. * @optval: The return value. * * Retrieves the value of a session option.  See #rtp_option for * documentation on the options and their legal values. * * Returns: TRUE and the value of the option in optval on success, else FALSE. */int rtp_get_option(struct rtp *session, rtp_option optname, int *optval){	switch (optname) {		case RTP_OPT_WEAK_VALIDATION:			*optval = session->opt->wait_for_rtcp;                        break;        	case RTP_OPT_PROMISC:			*optval = session->opt->promiscuous_mode;                        break;	        case RTP_OPT_FILTER_MY_PACKETS:			*optval = session->opt->filter_my_packets;			break;		case RTP_OPT_REUSE_PACKET_BUFS:			*optval = session->opt->reuse_bufs;			break;        	default:                        *optval = 0;			debug_msg("Ignoring unknown option (%d) in call to rtp_get_option().\n", optname);                        return FALSE;	}        return TRUE;}/** * rtp_get_userdata: * @session: The RTP session. * * This function returns the userdata pointer that was passed to the * rtp_init() or rtp_init_if() function when creating this session. * * Returns: pointer to userdata. */uint8_t *rtp_get_userdata(struct rtp *session){	check_database(session);	return session->userdata;}/** * rtp_my_ssrc: * @session: The RTP Session. *

⌨️ 快捷键说明

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