📄 synsyncto.c
字号:
/*------------------------------------------------------------------------- * synsyncto.c - synsyncto *------------------------------------------------------------------------- */#include <syn.h>#include <strings.h>#include <util.h>#include <math.h>#define DEBUG(x)#ifdef RTPLIB_SYNCHRONIZE/*----------------------------------------------------------------------- * synsyncto - synchronize a group of streams to a particular relation * or each other if relation time equals zero. On success the variables * syncx, syncx specify the "target" relation. * Note that synchronization is experimental and not well-tested. *----------------------------------------------------------------------- */intsynsyncto(struct synsession *pssn, struct cnamelist *pcnl, struct timespec *syncx, struct timespec *syncy){ struct stream *pstm; struct synstream *psstms[128]; struct timespec ytime, xtime, delta, zero, maxytime; mediatime_t lastsrts; int mediaoff; int i, j, psstmcnt; bool adjusted, init = TRUE, external = TRUE; unsigned int lastsrntp[2]; external = syncx->tv_sec != 0; memset(&maxytime, 0, sizeof(struct timespec)); memset(&zero, 0, sizeof(struct timespec)); for(pstm = pcnl->cn_stream, psstmcnt = 0; pstm != NULL && psstmcnt < 128; pstm = pstm->stm_cnamenext, psstmcnt++) { if ((psstms[psstmcnt] = syngetstream(pssn, pstm->stm_ssrc)) == NULL) continue; pthread_mutex_lock(&psstms[psstmcnt]->sstm_readmutex); /* * Check if stream is buffering */ if (psstms[psstmcnt]->sstm_buffering == TRUE) { pthread_mutex_unlock(&psstms[psstmcnt]->sstm_readmutex); synreleasestream(pssn, psstms[psstmcnt]); psstms[psstmcnt] = NULL; continue; } rtpctl(pssn->ssn_session, RTP_CTL_STREAM_LOCK, NULL, 0, pstm->stm_ssrc); rtpctl(pssn->ssn_session, RTP_CTL_STREAM_GETSRTS, (char *) &lastsrts, 0, pstm->stm_ssrc); rtpctl(pssn->ssn_session, RTP_CTL_STREAM_GETSRNTP, (char *) &lastsrntp, 0, pstm->stm_ssrc); rtpctl(pssn->ssn_session, RTP_CTL_STREAM_UNLOCK, NULL, 0, pstm->stm_ssrc); /* * Check if stream has yet received a SR. */ if (lastsrntp[RTP_NTPINT] == 0) { pthread_mutex_unlock(&psstms[psstmcnt]->sstm_readmutex); synreleasestream(pssn, psstms[psstmcnt]); psstms[psstmcnt] = NULL; continue; } /* * Convert NTP format to timespec_t. */ xtime.tv_sec = lastsrntp[RTP_NTPINT]; xtime.tv_nsec = (long) (((double) lastsrntp[RTP_NTPFRAC] / pow(2, 32)) * 1000000000); /* * Convert timestamp in last SR to corresponding local time */ ytime = timeadd(timeunflatten((lastsrts - psstms[psstmcnt]->sstm_clky), psstms[psstmcnt]->sstm_clkrt), psstms[psstmcnt]->sstm_clkx); /* * Use first NTP time for point on X-axis if no external value */ if (external == FALSE && init == TRUE) { *syncx = xtime; init = FALSE; } /* * Xlate relation to syncx, a common point on X-axis */ delta = timesub(xtime, *syncx); ytime = timesub(ytime, delta); /* * Find maximum y=f_ssrc(syncx) over all ssrc in list. * The stream with the maximum is the stream that lags * the furthest. */ if (timecmp(ytime, maxytime) < 0) maxytime = ytime; } /* * Check if the outside clock is ahead */ if (external == TRUE) { if (timecmp(maxytime, *syncy) < 0) { for (j = 0; j < psstmcnt; j++) if (psstms[j] != NULL) { pthread_mutex_unlock(&psstms[j]->sstm_readmutex); synreleasestream(pssn, psstms[j]); } *syncy = maxytime; return SYN_EXTERNALAHEAD; } } else *syncy = maxytime; DEBUG(printf("Synsync to: External: %s Maxytime %u\n", (external ? "Yes" : "No"), maxytime)); /* * Now make the asjustments. */ adjusted = FALSE; for(pstm = pcnl->cn_stream, i = 0; pstm != NULL && i < 128; pstm = pstm->stm_cnamenext, i++) { if (psstms[i] == NULL) continue; rtpctl(pssn->ssn_session, RTP_CTL_STREAM_LOCK, NULL, 0, pstm->stm_ssrc); rtpctl(pssn->ssn_session, RTP_CTL_STREAM_GETSRTS, (char *) &lastsrts, 0, pstm->stm_ssrc); rtpctl(pssn->ssn_session, RTP_CTL_STREAM_GETSRNTP, (char *) &lastsrntp, 0, pstm->stm_ssrc); rtpctl(pssn->ssn_session, RTP_CTL_STREAM_UNLOCK, NULL, 0, pstm->stm_ssrc); /* * Do same conversions to get y=f_stm(syncx) */ xtime.tv_sec = lastsrntp[RTP_NTPINT]; xtime.tv_nsec = (long) (((double) lastsrntp[RTP_NTPFRAC] / pow(2, 32)) * 1000000000); ytime = timeadd(timeunflatten((lastsrts - psstms[i]->sstm_clky), psstms[i]->sstm_clkrt), psstms[i]->sstm_clkx); delta = timesub(xtime, *syncx); ytime = timesub(ytime, delta); /* * Compute amount of change needed */ delta = timesub(*syncy, ytime); if (timecmp(delta, zero) < 0) { /* * Convert to media units and adjust */ mediaoff = timeflatten(delta, psstms[i]->sstm_clkrt); /* * Should there be caps on change? */ if (mediaoff > 0) { adjusted = TRUE; psstms[i]->sstm_clky -= mediaoff; mediaoff = -mediaoff; rtppostevent(pssn->ssn_session, EVENT_PARTICIPANT_SYNC, psstms[i]->sstm_ssrc, &mediaoff, sizeof(int)); } } pthread_mutex_unlock(&psstms[i]->sstm_readmutex); synreleasestream(pssn, psstms[i]); } if (adjusted == TRUE) return SYN_ADJUSTED; else return SYN_NOTADJUSTED; }#endif /* RTPLIB_SYNCHRONIZE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -