📄 rtcp.c
字号:
header.ssrc = ssrc;
header.bits = RTCP_HEADER_INIT;
header.bits = bitfieldSet(header.bits, count, HEADER_RC, HDR_LEN_RC);
header.bits = bitfieldSet(header.bits, type, HEADER_PT, HDR_LEN_PT);
header.bits = bitfieldSet(header.bits, W32Len(dataLen) - 1,
HEADER_len, HDR_LEN_len);
ConvertFromNetwork(&header, 0, W32Len(SIZEOF_RTCPHEADER));
return header;
}
static RvUint32 getLost(rtpSource *s)
{
RvUint32 extended_max;
RvUint32 expected;
RvInt32 received_interval;
RvInt32 expected_interval;
RvInt32 lost;
RvInt32 lost_interval;
RvUint8 fraction;
extended_max = s->cycles + s->max_seq;
expected = extended_max - s->base_seq + 1;
lost = expected - s->received;
expected_interval = expected - s->expected_prior;
s->expected_prior = expected;
received_interval = s->received - s->received_prior;
s->received_prior = s->received;
lost_interval = expected_interval - received_interval;
if (expected_interval == 0 || lost_interval <= 0)
fraction = 0;
else
fraction = (RvUint8)((lost_interval << 8) / expected_interval);
return (fraction << 24) + lost;
}
static RvUint32 getJitter(rtpSource *s)
{
return s->jitter >> 4;
}
static RvUint32 getSequence(rtpSource *s)
{
return s->max_seq + s->cycles;
}
/*
static RvBool socketCompare(rtcpSession *element1, rtcpSession *element2)
{
return (element1->socket == element2->socket);
}
*/
/* static RvBool ssrcCompare(rtcpInfo *element1, rtcpInfo *element2)
{
return (element1->ssrc == element2->ssrc);
} */
static void rtcpReceive_(RvSocketSelect* ss, RvSocketListener* sl, void *data)
{
rtcpSession* s = (rtcpSession*)sl->data;
RvSocketAddr fromAddr;
RvUint32 buffer[MAXRTCPPACKET/sizeof(RvUint32)+1];
RV_BUFFER buf;
if (s == NULL)
return;
rvMutexLock(&s->mutex);
buf = buffCreate(buffer, MAXRTCPPACKET);
buf.length = rvSocketRecvFrom(&s->socket, buf.buffer, buf.length, &fromAddr);
if (rvSocketAddrGetInetPort(&fromAddr) != rvSocketGetPort(&s->socket) ||
!isMyIP(&fromAddr))
rtcpProcessCompoundRTCPPacket((HRTCPSESSION)s, &buf, getNNTPTime());
rvMutexUnlock(&s->mutex);
}
static void rtcpTimerCallback(RvTimer *timer, void *data)
{
rtcpSession* s = (rtcpSession*)data;
RvUint32 buffer[MAXRTCPPACKET/sizeof(RvUint32)+1];
RV_BUFFER buf;
RvIpv4Addr ipv4;
RvSocketAddr toAddr;
rvMutexLock(&s->mutex);
buf = buffCreate(buffer,MAXRTCPPACKET);
rvTimerReset(&s->tElem, RTCP_TIMEOUT);
rtcpCreateRTCPPacket((HRTCPSESSION)s, &buf);
rvIpv4AddrConstruct(&ipv4, s->ip);
rvSocketAddrConstructIpv4(&toAddr, &ipv4, s->port);
rvSocketSendTo(&s->socket, buf.buffer, buf.length, &toAddr);
rvMutexUnlock(&s->mutex);
}
/* == Internal RTCP Functions == */
RVVXDAPI
RvInt32 VXDCALLCONV rtcpCreateRTCPPacket(
IN HRTCPSESSION hRTCP,
IN OUT RV_BUFFER * buf)
{
rtcpSession *s = (rtcpSession *)hRTCP;
rtcpHeader head;
RvUint32 allocated = 0;
RV_BUFFER bufC;
rtcpType type = RTCP_SR;
rvMutexLock(&s->mutex);
if (buffValid(buf, SIZEOF_RTCPHEADER + SIZEOF_SR))
{
RvUint64 myTime = s->myInfo.eSR.tNNTP;
RvUint8 cc = 0;
RvListIter(rtcpInfo) iter;
allocated = SIZEOF_RTCPHEADER;
if (s->myInfo.active)
{
s->myInfo.active = rvFalse;
bufC = buffCreate(&(s->myInfo.eSR), SIZEOF_SR);
buffAddToBuffer(buf, &bufC, allocated);
ConvertToNetwork(buf->buffer + allocated, 0, W32Len(bufC.length));
allocated += SIZEOF_SR;
}
else
{
type = RTCP_RR;
}
for(iter = rvListBegin(&s->hList); iter != rvListEnd(&s->hList); iter = rvListIterNext(iter))
{
rtcpInfo *info = rvListIterData(iter);
if (info->active)
{
info->eToRR.bfLost = getLost (&(info->src));
info->eToRR.nJitter = getJitter (&(info->src));
info->eToRR.nExtMaxSeq = getSequence(&(info->src));
info->eToRR.tDLSR =
(info->tLSRmyTime) ?
(reduceNNTP(myTime)-info->tLSRmyTime) :
0;
bufC = buffCreate(&(info->eToRR), SIZEOF_RR);
if (buffAddToBuffer(buf, &bufC, allocated))
{
cc++;
if (cc == 32)
break;
ConvertToNetwork(buf->buffer + allocated, 0,
W32Len(bufC.length));
allocated += SIZEOF_RR;
}
info->active = rvFalse;
}
}
head = makeHeader(s->myInfo.ssrc, cc, type, (RvUint16)allocated);
bufC = buffCreate(&head, SIZEOF_RTCPHEADER);
buffAddToBuffer(buf, &bufC, 0);
/* add an CNAME SDES packet to the compound packet */
if (buffValid(buf,
allocated + SIZEOF_RTCPHEADER + SIZEOF_SDES(s->myInfo.eCName)))
{
RV_BUFFER sdes_buf;
/* 'sdes_buf' is inside the compound buffer 'buf' */
sdes_buf = buffCreate(buf->buffer + allocated,
(SIZEOF_RTCPHEADER + SIZEOF_SDES(s->myInfo.eCName)));
head = makeHeader(s->myInfo.ssrc, 1, RTCP_SDES,
(RvUint16)sdes_buf.length);
memcpy(sdes_buf.buffer, (char *)&head, SIZEOF_RTCPHEADER);
memcpy(sdes_buf.buffer + SIZEOF_RTCPHEADER, &(s->myInfo.eCName),
SIZEOF_SDES(s->myInfo.eCName));
allocated += sdes_buf.length;
}
if (s->myInfo.collision == 1 &&
buffValid(buf, allocated + SIZEOF_RTCPHEADER))
{
head = makeHeader(s->myInfo.ssrc, 1, RTCP_BYE,
SIZEOF_RTCPHEADER);
bufC = buffCreate(&head, SIZEOF_RTCPHEADER);
buffAddToBuffer(buf, &bufC, allocated);
s->myInfo.collision = 2;
allocated += SIZEOF_RTCPHEADER;
}
}
buf->length = allocated;
rvMutexUnlock(&s->mutex);
return 0;
}
RVVXDAPI
RvInt32 VXDCALLCONV rtcpProcessRTCPPacket(
IN rtcpSession * s,
IN RvUint8 * data,
IN RvInt32 dataLen,
IN rtcpType type,
IN RvInt32 reportCount,
IN RvUint64 myTime)
{
RvListIter(rtcpInfo) iter;
unsigned scanned = 0;
rtcpInfo *fInfo = NULL;
RvUint32 ssrc;
if (dataLen == 0)
return 0;
rvMutexLock(&s->mutex);
switch(type)
{
case RTCP_SR:
case RTCP_RR:
{
ConvertToNetwork(data, 0, 1);
ssrc = *(RvUint32 *)(data);
scanned = sizeof(RvUint32);
if (ssrc == s->myInfo.ssrc)
{
s->myInfo.collision = 1;
rvMutexUnlock(&s->mutex);
return ERR_RTCP_SSRCCOLLISION;
}
for(iter = rvListBegin(&s->hList); iter != rvListEnd(&s->hList); iter = rvListIterNext(iter))
{
if(rvListIterData(iter)->ssrc == ssrc)
{
fInfo = rvListIterData(iter);
break;
}
}
if (fInfo == NULL) /* New source */
{
/* Initialize info */
rtcpInfo info;
memset(&info, 0, sizeof(info));
info.ssrc = *(RvUint32 *)(data);
info.eToRR.ssrc = info.ssrc;
info.active = rvFalse;
info.src.probation = MIN_SEQUENTIAL - 1;
rvListPushFront(rtcpInfo)(&s->hList, &info);
fInfo = rvListFront(&s->hList);
}
break;
}
default:
break;
}
/* process the information */
switch(type)
{
case RTCP_SR:
{
ConvertToNetwork(data + scanned, 0, W32Len(sizeof(rtcpSR)));
if (fInfo)
{
fInfo->eSR = *(rtcpSR *)(data + scanned);
fInfo->eToRR.tLSR = reduceNNTP(fInfo->eSR.tNNTP);
fInfo->tLSRmyTime = reduceNNTP(myTime);
}
scanned += SIZEOF_SR;
}
/* fall into RR */
case RTCP_RR:
{
if (fInfo)
{
int i;
rtcpRR* rr = (rtcpRR*)(data + scanned);
s->rtt += computeRoundTripTime(rr);
++s->numOfRRs;
ConvertToNetwork(data + scanned, 0,
reportCount * W32Len(sizeof(rtcpRR)));
for (i=0; i < reportCount; i++)
{
if (rr[i].ssrc == s->myInfo.ssrc)
{
fInfo->eFromRR = rr[i];
break;
}
}
}
break;
}
case RTCP_SDES:
{
int i;
rtcpSDES *sdes;
for (i = 0; i < reportCount; i++)
{
ConvertToNetwork(data + scanned, 0, 1);
ssrc = *(RvUint32 *)(data + scanned);
sdes = (rtcpSDES *)(data + scanned + sizeof(ssrc));
for(iter = rvListBegin(&s->hList); iter != rvListEnd(&s->hList); iter = rvListIterNext(iter))
{
fInfo = rvListIterData(iter);
if(fInfo->ssrc == ssrc)
{
switch(sdes->type)
{
case RTCP_SDES_CNAME:
memcpy(&(fInfo->eCName), sdes,
SIZEOF_SDES(*sdes));
fInfo->eCName.value[sdes->length] = 0;
break;
/* known SDES types that are not handled:
case RTCP_SDES_END:
case RTCP_SDES_NAME:
case RTCP_SDES_EMAIL:
case RTCP_SDES_PHONE:
case RTCP_SDES_LOC:
case RTCP_SDES_TOOL:
case RTCP_SDES_NOTE:
case RTCP_SDES_PRIV:
break; */
}
break;
}
scanned += SIZEOF_SDES(*sdes) + sizeof(RvUint32);
}
}
break;
}
case RTCP_BYE:
{
int i;
for (i = 0; i < reportCount; i++)
{
ConvertToNetwork(data + scanned, 0, 1);
ssrc = *(RvUint32 *)(data + scanned);
scanned += sizeof(ssrc);
for(iter = rvListBegin(&s->hList); iter != rvListEnd(&s->hList); iter = rvListIterNext(iter))
{
fInfo = rvListIterData(iter);
if(fInfo->ssrc == ssrc)
{
fInfo->invalid = rvTrue;
fInfo->ssrc = 0;
break;
}
}
}
break;
}
case RTCP_APP:
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -