www.pudn.com > RTP通用开发库(for Linux).rar > rtpupdate.c


/*-------------------------------------------------------------------------
 * rtpupdate.c - rtpupdate, rtpinitseq, rtpupdateseq
 *-------------------------------------------------------------------------
 */

#include 
#include 
#include 

#define DEBUG(x) x

/*------------------------------------------------------------------------
 * rtpupdate - update statistics with each RTP packet received. 
 *------------------------------------------------------------------------
 */
int
rtpupdate(struct session *psn, struct stream *pstm, struct rtp *header)
{

	struct timespec	now;
	int		delta;
	int		D;

	if (pthread_mutex_lock(&pstm->stm_mutex) != 0)
		return ERROR;

	if (rtpupdateseq(psn, pstm, header->rtp_seq) == ERROR) {
		pthread_mutex_unlock(&pstm->stm_mutex);
		return ERROR;
	}

	clock_gettime(CLOCK_REALTIME, &now);

	/*
	 * Check for encoding change.
	 * Post event if detected.
	 */
	if (pstm->stm_payload != header->rtp_payload) {
		pstm->stm_payload = header->rtp_payload;
		rtppostevent(psn, EVENT_PARTICIPANT_ENCODING, pstm->stm_ssrc, NULL, 0);
	}
  
	/*
	 * If not first packet, update jitter.
	 */
	if (pstm->stm_packets != 0) {
		if (pstm->stm_clkrt != 0) {
			delta = timeflatten(timesub(now, pstm->stm_lastrec), pstm->stm_clkrt);
			D = delta - (header->rtp_time - pstm->stm_lastts);
			D = (D < 0 ? -D : D);
			pstm->stm_jitter += ((double) D - pstm->stm_jitter) / (double) 16;
		}
	}
  
	pstm->stm_packets++;
	pstm->stm_inactive = 0;
	pstm->stm_lastts = header->rtp_time;
	pstm->stm_lastrec = now;
	pthread_mutex_unlock(&pstm->stm_mutex);
	return OK;
}

/*------------------------------------------------------------------------
 * rtpinitseq - initialize variables related to sequence numbers
 * Adapted from RFC 1889.
 *------------------------------------------------------------------------
 */
void
rtpinitseq(struct stream *pstm, seq_t seq)
{

	pstm->stm_firstseq = seq;
	pstm->stm_hiseq = seq;
	pstm->stm_roll = 0;
	pstm->stm_packets = 0;
	pstm->stm_recprior = 0;
	pstm->stm_expprior = 0;  
}

/*------------------------------------------------------------------------
 * rtpupdateseq - check sequence number of incoming packet and update
 * appropriate counters. Adapted from RFC 1889.
 *------------------------------------------------------------------------
 */
int
rtpupdateseq(struct session *psn, struct stream *pstm, seq_t seq)
{

	seq_t udelta;

	udelta = seq - pstm->stm_hiseq;
  
	if (pstm->stm_probation) {
		if (seq == pstm->stm_hiseq + 1) {
			pstm->stm_probation--;
			pstm->stm_hiseq = seq;
			if (pstm->stm_probation == 0) {
				rtpinitseq(pstm, seq);
				return OK;
			}
		} else {
			pstm->stm_probation = RTP_MINSEQUENTIAL - 1;
			pstm->stm_hiseq = seq;
		}
		return ERROR;
	} 
	else
		if (udelta < RTP_MAXDROPOUT) {
			if (seq < pstm->stm_hiseq)
				pstm->stm_roll++;
			pstm->stm_hiseq = seq;
		}
		else
			if (udelta <= RTP_SEQMOD - RTP_MAXMISORDER) {
				if (seq == pstm->stm_badseq) {
					rtpinitseq(pstm, seq);
					rtppostevent(psn, EVENT_PARTICIPANT_SEQGAP,
						     pstm->stm_ssrc, NULL, 0);
				}
			}
			else {
				pstm->stm_badseq = (seq + 1) & (RTP_SEQMOD - 1);
				return ERROR;
			}
	return OK;
}