📄 rtcpcycle.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 + -