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

📄 rtcpcycle.c

📁 linux环境下用纯c写的RTP协议的通用开发库
💻 C
字号:
/*------------------------------------------------------------------------- * rtcpcycle.c - rtcpcycle, rtcpcycleupdate *------------------------------------------------------------------------- */#include <time.h>#include <util.h>#include <rtp.h>#include <hash.h>#include <rtcp.h>#include <unistd.h>#include <stdlib.h>/*------------------------------------------------------------------------ * rtcpcycle - do cyclic update on streams and genereate receiver reports. * Rtcycle returns seconds to wait until next rtcpcycle. *------------------------------------------------------------------------ */doublertcpcycle(struct session *psn){	struct rtcp         *prtcp, *ppacket;	struct rr           *prr;	struct rblock       *prb;	int                 i, count, packets, bytes, active;	int                 streamcount;	ssrc_t              *sources;	struct stream       **pstreams;	/*	 * Get pointers to pre-allocated (in rtpopen) memory.	 */	sources = psn->sn_cyclesources;	pstreams = (struct stream **) sources;	/* 	 * Get list of sources in session.	 */	streamcount = rtpsources(psn, sources, RTCP_RRMAXRBLOCKS);	if (streamcount <= 0)		return rtcpinterval(1, 0,				    psn->sn_bw * RTCP_BWFRAC, FALSE, 				    0, &psn->sn_avgrtcp, FALSE);  	/*	 * Iterate over SSRC list. Lookup each stream and	 * determins if stream was active in previous RTCP	 * cycle.	 */	for (i = 0, active = 0; i < streamcount; i++) {		/*		 * Hold on to the 32-bit pointers that will be returned		 * by rtpgetstream in the space previously used by the		 * 32-bit SSRC ID. The pointer is needed to release the		 * stream structure later by calling rtpreleasestream.		 */		pstreams[i] = rtpgetstream(psn, sources[i]);		if (pstreams[i] == NULL)			continue;		if (!RTP_INACTIVE(pstreams[i]->stm_inactive) && RTP_DATASEEN(pstreams[i])) {			active++;			/*			 * Mark this stream for rblock generation.			 */			pstreams[i]->stm_mark = TRUE;		}	}	/*	 * Determine how many RTCP packets (within a compund packet	 * must be sent. Each RTCP receiver report packet can hold only	 * 31 reveiver report blocks (rblocks).	 */	packets = active / RTCP_MAXRBLOCKS + ((active % RTCP_MAXRBLOCKS) != 0);	bytes = active * sizeof(struct rblock) + packets * (RTCP_HEADERSZ + sizeof(ssrc_t));	ppacket = (struct rtcp *) psn->sn_cyclebuf;	prtcp = ppacket;	prr = (struct rr *) prtcp->rtcp_data;	prb = (struct rblock *) prr->rr_rb;	/*	 * Iterate over the list of streams again, calling 	 * rtcpcycleupdate on each to update its statistics	 * and generate an rblock if the streams stm_mark	 * flag is set.	 */	for (i = 0, count = 0; i < streamcount; i++) {		if (pstreams[i] == NULL)			continue;		if (rtcpcycleupdate(psn, pstreams[i], prb) == FALSE) 			continue;		count++;		prb++;          		if (count == RTCP_MAXRBLOCKS || i + 1 == streamcount) {  			/* 			 * An RTCP receiver report can only hold 31 report blocks.			 * When the maximum is reached *or* the last source in 			 * the list of SSRCs is processed, generate an RTCP header.			 */			rtcpheader(prtcp, count, RTCP_RR, sizeof(struct rblock) * count + RTCP_HEADERSZ + sizeof(ssrc_t));			prtcp->rtcp_length = htons(prtcp->rtcp_length);			prr->rr_ssrc = htonl(psn->sn_ssrc);      			/*			 * If there are streams remaining in the list,			 * advance the pointers to the next rtcp packet.			 */			if (i + 1 != streamcount) {				prtcp = (struct rtcp *) (prb + 1);				prr = (struct rr *) prtcp->rtcp_data;				prb = (struct rblock *) prr->rr_rb;				count = 0;			}		}	}  	/*	 * Send the compound RTCP packet.	 */	rtcpsend(psn, ppacket, bytes);	/* 	 * Release all the streams.	 */	for (i = 0; i < streamcount; i++) 		if (pstreams[i] != NULL)			rtpreleasestream(psn, pstreams[i]);	/*	 * Return the number of seconds to wait before invoking	 * rtcpcycle again.	 */	return rtcpinterval(streamcount + 1, active, psn->sn_bw * RTCP_BWFRAC, FALSE, bytes + 28, &psn->sn_avgrtcp, FALSE);}/*------------------------------------------------------------------------ * rtcpcycleupdate - update stream stats and generate an rblock if * requested. Rtcpcycleupdate returns TRUE if an rblock is generated. *------------------------------------------------------------------------ */boolrtcpcycleupdate(struct session *psn, struct stream *pstm, struct rblock *prb){	int	        exthiseq, cumexpected, lostcycle, expcycle, reccycle;	int		cumlost;	struct timespec	now;	pthread_mutex_lock(&pstm->stm_mutex);	/* 	 * Determine if the participant has timed out.	 */	if (RTP_DATASEEN(pstm) == FALSE && !RTP_INACTIVE(pstm->stm_inactive))		if (++pstm->stm_inactive >= pstm->stm_inactthresh &&		    pstm->stm_inactthresh != RTP_INFINITEINACTIVETHRESH) {			pstm->stm_inactive = RTP_TIMEDOUT;			pthread_mutex_unlock(&pstm->stm_mutex);			rtpstreamcleanup(psn, pstm);			rtppostevent(psn, EVENT_PARTICIPANT_TIMEOUT, pstm->stm_ssrc, NULL, 0);			return FALSE;		}	/*	 * Update statistics that must be updated once per 	 * RTCP cycle.	 */	exthiseq = (pstm->stm_roll << 16) | pstm->stm_hiseq;	cumexpected = exthiseq - pstm->stm_firstseq + 1;	cumlost = cumexpected - pstm->stm_packets;  	/*	 * If the stream is marked for rblock generation	 * write the rblock in the area pointed to by prb.	 */	if (pstm->stm_mark == TRUE && prb != NULL) {		prb->rb_ssrc = htonl(pstm->stm_ssrc);		prb->rb_hiseq = htonl(exthiseq);		prb->rb_jitter = htonl((unsigned int) pstm->stm_jitter);		/*		 * Cap cumlost to appropriate max/min values for 		 * a 24-bit signed integer.		 */		prb->rb_cumlost = hton24(max(min(cumexpected - (int) pstm->stm_packets, 0x7fffff), -(1 << 23)));		expcycle = cumexpected - pstm->stm_expprior;		reccycle = pstm->stm_packets - pstm->stm_recprior;		lostcycle = max(expcycle - reccycle, 0);		prb->rb_fraclost = (expcycle == 0 ? 0 : (lostcycle << 8) / expcycle);    		/*		 * Extract middle 32 bits of last sender		 * report NTP timestamp.		 */		prb->rb_lastsrts = htonl(((pstm->stm_lastntp[1] & 0x0000ffff) << 16) |					 ((pstm->stm_lastntp[0] & 0xffff0000) >> 16));		/*		 * Compute the delay since last sender		 * report, if one has been received.		 */		if (pstm->stm_lastsr.tv_sec != 0) {			clock_gettime(CLOCK_REALTIME, &now);			prb->rb_delay = htonl(timeflatten(timesub(now, pstm->stm_lastsr), 65536));		}    	}	pstm->stm_expprior = cumexpected;	pstm->stm_recprior = pstm->stm_packets;	pthread_mutex_unlock(&pstm->stm_mutex);	if (pstm->stm_mark == TRUE) {		pstm->stm_mark = FALSE;		return TRUE;	}	else		return FALSE;}

⌨️ 快捷键说明

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