📄 rtcptransmitter.cpp
字号:
#include <libc\assert.h>
#include <libc\sys\time.h>
#include <libc\string.h>
#include <libc\stdlib.h>
#include <libc\sys\unistd.h>
#include "vtypes.h"
#include "cpLog.h"
#include "rtpTypes.h"
#include "rtpTools.h"
#include "NtpTime.h"
#include "RtpTransmitter.h"
#include "RtcpTransmitter.h"
const int RtcpTransmitter::RTCP_INTERVAL = 5000;
/* ----------------------------------------------------------------- */
/* --- RtcpTransmitter Constructor --------------------------------- */
/* ----------------------------------------------------------------- */
RtcpTransmitter::RtcpTransmitter (CSocketUdp * udp,const char* /*remoteHost*/,
int /*remoteMinPort*/,
int /*remoteMaxPort*/,
RtcpReceiver* receiver)
{
if (receiver)
{
myStack = udp;
freeStack = false;
}
else
{
myStack = udp;
freeStack = true;
}
remoteAddr = udp->getDestination();
constructRtcpTransmitter ();
}
RtcpTransmitter::RtcpTransmitter (CSocketUdp * udp,const char* /*remoteHost*/,
int /*remotePort*/,
RtcpReceiver* receiver)
{
if (receiver)
{
freeStack = false;
}
else
{
freeStack = true;
}
myStack = udp;
remoteAddr = udp->getDestination();
constructRtcpTransmitter ();
}
void RtcpTransmitter::constructRtcpTransmitter ()
{
tran = NULL;
recv = NULL;
rtcpRecv = NULL;
SDESInfo = NULL;
// prepare for rtcp timing intervals
nextInterval = getNtpTime();
updateInterval();
}
RtcpTransmitter::~RtcpTransmitter ()
{
if (freeStack)
{
delete myStack;
myStack = 0;
}
if ((tran) && (SDESInfo))
{
delete SDESInfo;
SDESInfo = NULL;
}
tran = NULL;
recv = NULL;
rtcpRecv = NULL;
}
void
RtcpTransmitter::setRemoteAddr ( NetworkAddress& theAddr)
{
remoteAddr = theAddr;
}
/* --- send packet functions --------------------------------------- */
int RtcpTransmitter::transmit (RtcpPacket* p)
{
myStack->transmitTo ((char*)p->getPacketData(),
p->getTotalUsage(),
&remoteAddr);
// exit with sucess
return 0;
}
void RtcpTransmitter::updateInterval ()
{
// RTCP_INTERVAL random offset between (.5 to 1.5)
int delayMs = RTCP_INTERVAL * (500 + rand() / (RAND_MAX / 1000)) / 1000;
nextInterval = nextInterval + delayMs;
}
int RtcpTransmitter::checkInterval ()
{
if (getNtpTime() > nextInterval)
{
// prepare for next interval
updateInterval();
return 1;
}
// time not up yet
return 0;
}
/* --- SR/RR RTCP report packets------------------------------------ */
int RtcpTransmitter::addSR (RtcpPacket* p, int npadSize)
{
// header
RtcpHeader* header = reinterpret_cast < RtcpHeader* > (p->freeData());
int usage = p->allocData (sizeof(RtcpHeader));
header->version = RTP_VERSION;
header->padding = (npadSize > 0) ? 1 : 0;
header->count = 0;
header->type = (tran) ? rtcpTypeSR : rtcpTypeRR;
NtpTime nowNtp = getNtpTime();
// sender information
if (tran)
{
//cpLog (LOG_DEBUG_STACK, "RTCP: Making Sender Info");
RtcpSender* senderInfo = reinterpret_cast < RtcpSender* > (p->freeData());
usage += p->allocData (sizeof(RtcpSender));
int diffNtp = 0;
if (nowNtp > tran->seedNtpTime)
diffNtp = nowNtp - tran->seedNtpTime;
else
if (tran->seedNtpTime > nowNtp)
diffNtp = tran->seedNtpTime - nowNtp;
RtpTime diffRtp = (diffNtp * tran->networkFormat_clockRate) / 1000;
senderInfo->ssrc = htonl(tran->ssrc);
senderInfo->ntpTimeSec = htonl(nowNtp.getSeconds());
senderInfo->ntpTimeFrac = htonl(nowNtp.getFractional());
senderInfo->rtpTime = htonl(tran->seedRtpTime + diffRtp);
senderInfo->packetCount = htonl(tran->packetSent);
senderInfo->octetCount = htonl(tran->payloadSent);
}
else
{
RtcpChunk* chunk = reinterpret_cast < RtcpChunk* > (p->freeData());
usage += p->allocData (sizeof(RtpSrc));
chunk->ssrc = 0 ; /* if recv only, give src 0 for receiver for now */
}
// report blocks
if ((rtcpRecv) && (rtcpRecv->getTranInfoCount() > 0))
{
//cpLog (LOG_DEBUG_STACK, "RTCP: Making Report Block");
RtpTranInfo* tranInfo = NULL;
RtpReceiver* recvInfoSpec = NULL;
RtcpReport* reportBlock = NULL;
for (int i = 0; i < rtcpRecv->getTranInfoCount(); i++)
{
tranInfo = rtcpRecv->getTranInfoList(i);
recvInfoSpec = tranInfo->recv;
// only receieved RTCP packets from transmitter
if (recvInfoSpec == NULL)
continue;
// don't report on probation transmitters
if (recvInfoSpec->probation < 0)
continue;
//cpLog (LOG_DEBUG_STACK, "RTCP: Report block for src %d",
// recvInfoSpec->ssrc);
reportBlock = reinterpret_cast < RtcpReport* > (p->freeData());
usage += p->allocData (sizeof(RtcpReport));
reportBlock->ssrc = htonl(recvInfoSpec->ssrc);
reportBlock->fracLost = calcLostFrac(tranInfo);
u_int32_t lost = (calcLostCount(tranInfo)) & 0xffffff;
reportBlock->cumLost[2] = lost & 0xff;
reportBlock->cumLost[1] = (lost & 0xff00) >> 8;
reportBlock->cumLost[0] = (lost & 0xff0000) >> 16;
reportBlock->recvCycles = htons(recvInfoSpec->recvCycles);
reportBlock->lastSeqRecv = htons(recvInfoSpec->prevSeqRecv);
// fracational
// reportBlock->jitter = htonl((u_int32_t)recvInfoSpec->jitter);
// interger
// if (recvInfoSpec->jitter > 0)
reportBlock->jitter = htonl(recvInfoSpec->jitter >> 4);
reportBlock->lastSRTimeStamp = htonl(tranInfo->lastSRTimestamp);
// reportBlock->lastSRDelay in the unit of 1/65536 of sec ??
// currently it is in ms
if (tranInfo->lastSRTimestamp == 0)
reportBlock->lastSRDelay = 0;
else
{
NtpTime thenNtp = tranInfo->recvLastSRTimestamp;
// NtpTime thenNtp ((tranInfo->lastSRTimestamp >> 16) |
// (nowNtp.getSeconds() & 0xffff0000),
// tranInfo->lastSRTimestamp << 16);
reportBlock->lastSRDelay = 0;
if (nowNtp > thenNtp)
reportBlock->lastSRDelay = htonl(nowNtp - thenNtp);
else
reportBlock->lastSRDelay = 0;
}
// next known transmitter
header->count++;
}
}
// profile-specific extensions
// future: not implemented
// padding
if (npadSize > 0)
{
// future: not implemented
assert (0);
}
// overall packet must ends on 32-bit count
assert (usage % 4 == 0);
header->length = htons((usage / 4) - 1);
//cpLog (LOG_DEBUG_STACK, "RTCP: SR/RR packet used %d bytes/ %d words",
// usage, usage/4);
return usage;
}
u_int32_t RtcpTransmitter::calcLostFrac (RtpTranInfo* s)
{
/* from A.3 of RFC 1889 - RTP/RTCP Standards */
RtpReceiver* r = s->recv;
u_int32_t expected = ((r->recvCycles + r->prevSeqRecv) - r->seedSeq + 1);
u_int32_t expected_interval, received_interval, lost_interval;
expected_interval = expected - s->expectedPrior;
s->expectedPrior = expected;
received_interval = r->packetReceived - s->receivedPrior;
s->receivedPrior = r->packetReceived;
lost_interval = expected_interval - received_interval;
u_int32_t fraction;
if (expected_interval == 0 || lost_interval <= 0) fraction = 0;
else fraction = (lost_interval << 8) / expected_interval;
return fraction;
}
u_int32_t RtcpTransmitter::calcLostCount (RtpTranInfo* s)
{
/* from A.3 of RFC 1889 - RTP/RTCP Standards */
RtpReceiver* r = s->recv;
u_int32_t expected = ((r->recvCycles + r->prevSeqRecv) - r->seedSeq + 1);
return expected - r->packetReceived;
}
/* --- SDES RTCP packet -------------------------------------------- */
int RtcpTransmitter::addSDES (RtcpPacket* p, RtcpSDESType item, int npadSize)
{
if (!tran) return -1;
RtcpSDESType list[2];
list[0] = item;
list[1] = rtcpSdesEnd;
return addSDES (p, list, npadSize);
}
int RtcpTransmitter::addSDES (RtcpPacket* p, int npadSize)
{
if (!tran) return -1;
RtcpSDESType list[8];
int i = 0;
if (strlen(getSdesCname()) > 0) list[i++] = rtcpSdesCname;
if (strlen(getSdesName()) > 0) list[i++] = rtcpSdesName;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -