📄 rtpreceiver.cpp
字号:
if( myStack->SelectRTPStack() ==0)
return NULL;
// create packet
RtpPacket* p = new RtpPacket (RECV_BUF);
assert (p);
// receive packet
int len = myStack->RTPreceive((char*)p->getHeader(), p->getPacketAlloc());
p->setTotalUsage (len);
// check packet
if( !p->isValid() )
{
cpLog(LOG_ERR, "****Packet is not valid");
delete p; p = NULL;
return NULL;
}
int dtmf_num = p->getPayloadType();
//modify for amr transmit,amr payloadtype = 121
if((dtmf_num >100 && dtmf_num<190) && (dtmf_num != 121))
p->setPayloadType(rtpPayloadDTMF_RFC2833);
// check if rtp ent
if (p->getPayloadType() == rtpPayloadDTMF_RFC2833)
{
if( recvEvent( p )==true)
{
isEvent=true;
m_event=getDTMFEvent();
return p; //add by huzx and delete blow
}
}
// update receiver info
// function may return 1, meaning packet
// out of seq tolr or source not valid
if (updateSource(p))
{
int port=getPort ();
cpLog(LOG_ERR, "myport is %d,",port);
cpLog(LOG_ERR, "****Packet is discarded or source not valid");
delete p; p = NULL;
return NULL;
}
return p;
}
int RtpReceiver::updateSource (RtpPacket* p)
{
// check if ssrc in probation list
if (sourceSet && p->getSSRC() == srcProbation && probationSet)
// old probation packets still in que
return 1;
// drop SID packets when SID packets are beginning packets
if ((p->getPayloadUsage() < ( networkFormat_payloadSize / 3 )) ||
(p->getPayloadUsage() < 20) )
{
cpLog( LOG_DEBUG_STACK, "Dropping SID packet" );
prevSeqRecv = p->getSequence();
return 1;
}
// new source found or resync old source
if (!sourceSet || p->getSSRC() != ssrc)
{
if (addSource(p))
return 1;
}
// no vaild source yet
assert (probation >= 0);
// drop CN packets
if ((p->getPayloadType() == rtpPayloadCN) ||
(p->getPayloadType() == 13)) {
cpLog(LOG_DEBUG_STACK, "drop 1 rtpPayloadCN packet");
prevSeqRecv = p->getSequence(); // drop comfort noise packet
return 1;
}
if (p->getPayloadType() != networkFormat )
{
cpLog(LOG_DEBUG, "Transmitter changing payload parameters(%d/%d) (%d/%d)",
p->getPayloadType(), networkFormat,
p->getPayloadUsage(), networkFormat_payloadSize );
p->printPacket();
initSource(p);
}
// fix rtp time stamp boundry
if ((( prevPacketRtpTime + network_pktSampleSize ) != p->getRtpTime()) &&
((( p->getRtpTime() - prevPacketRtpTime) * 1.0) / network_pktSampleSize < 1.5) &&
((( p->getRtpTime() - prevPacketRtpTime) * 1.0) / network_pktSampleSize> 0.5))
{
network_pktSampleSize = p->getRtpTime() - prevPacketRtpTime;
cpLog( LOG_DEBUG_STACK, "Fixing network_pktSampleSize to %d", network_pktSampleSize );
}
// check if valid sequence window
RtpSeqNumber seq = p->getSequence();
if ( RtpSeqGreater(seq, prevSeqRecv) ) // future packet
{
if (seq > prevSeqRecv)
{
if ( (seq - prevSeqRecv) > MISORDER )
{
// large sequence jump forward, skip over packets less then seq
cpLog(LOG_DEBUG_STACK, "jump to %d (%d jumps)", seq, seq - prevSeqRecv);
cpLog(LOG_DEBUG_STACK, "rtpTime %u, prevPacketRtpTime %u", p->getRtpTime(), prevPacketRtpTime);
prevSeqRecv = seq - 1;
prevPacketRtpTime = p->getRtpTime() - network_pktSampleSize;
}
}
else if ( (seq + RTP_SEQ_MOD - prevSeqRecv) > MISORDER)
{
cpLog(LOG_DEBUG_STACK, "jump cycle to %d (%d jumps)", seq, seq + RTP_SEQ_MOD - prevSeqRecv );
cpLog(LOG_DEBUG_STACK, "rtpTime %u, prevPacketRtpTime %u", p->getRtpTime(), prevPacketRtpTime);
prevSeqRecv = seq - 1;
prevPacketRtpTime = p->getRtpTime() - network_pktSampleSize;
}
}
else if ( RtpSeqGreater(prevSeqRecv, seq) ) // past packet
{
// check if the pkt is too late comparing to the pkt already
// played. Since the prevSeqPlay is irrelavant due to diff
// api_payload Size, use inPos and playPos to calculate.
int size = networkFormat_payloadSize;
int backNoOfSeq = (prevSeqRecv > seq) ?
(prevSeqRecv - seq) : (prevSeqRecv + RTP_SEQ_MOD - seq );
if (inPos > playPos)
{
if ((inPos - (backNoOfSeq + 1) * size) < playPos)
{
cpLog(LOG_DEBUG_STACK, "too late now: discard seq %d", seq);
return 1;
}
}
else
{
if ((inPos + IN_BUFFER_SIZE - (backNoOfSeq + 1) * size) < playPos)
{
cpLog(LOG_DEBUG_STACK, "too late now: discard seq %d", seq);
return 1;
}
}
}
else // (seq == prevSeqRecv) // present packet
{
// duplicate with previous packet
//cpLog(LOG_DEBUG_STACK,"duplicate packet %d", seq);
//return 1;
}
return 0;
}
int RtpReceiver::addSource(RtpPacket* p)
{
// don't allow ssrc changes without removing first
if (sourceSet)
{
if (probation < 4)
{
probation ++;
int port=getPort ();
cpLog(LOG_ERR, "myport is %d,probation is %d",port,probation);
cpLog(LOG_ERR, "Rejecting new transmitter %u, keeping %u",p->getSSRC(), ssrc);
return 1;
}
else
removeSource(ssrc);
}
// check if ssrc in probation list
if (sourceSet && p->getSSRC() == srcProbation && probationSet)
return 1;
sourceSet = true;
ssrc = p->getSSRC();
cpLog(LOG_DEBUG_STACK, "Received ssrc = %u", ssrc);
probation = 0;
packetReceived = 0;
payloadReceived = 0;
// init SDES and RTCP fields
if (rtcpRecv)
rtcpRecv->addTranInfo(ssrc, this);
initSource (p);
return 0;
}
void RtpReceiver::initSource (RtpPacket* p)
{
assert (ssrc == p->getSSRC());
cpLog(LOG_DEBUG_STACK, "InitSource %u with sequence %d and rtp time %u",
ssrc, p->getSequence(), p->getRtpTime());
seedSeq = p->getSequence();
seedNtpTime = getNtpTime();
seedRtpTime = p->getRtpTime();
// set receiving codec
//If codec is G711, paylaod size cannot change, if it does it is
//an error, just drop the packet
if((p->getPayloadType() == 0) &&
(p->getPayloadUsage() != networkFormat_payloadSize))
{
cpLog(LOG_ERR, "Incorrect payload size (%d) for payload type (%d), expected (%d) ignoring packet",
p->getPayloadUsage(), p->getPayloadType(), networkFormat_payloadSize);
}
else if ((p->getPayloadType() != networkFormat) ||
(p->getPayloadUsage() != networkFormat_payloadSize))
{
int networkFormat_org = networkFormat;
int network_pktSampleSize_org = network_pktSampleSize;
int networkFormat_payloadSize_org = networkFormat_payloadSize;
float multiplier = (p->getPayloadUsage() * 1.0) / (networkFormat_payloadSize * 1.0);
float new_samples = multiplier * (network_pktSampleSize * 1.0);
setNetworkFormat( p->getPayloadType(),
(int) new_samples,
0, p);
if (networkFormat_perSampleSize)
network_pktSampleSize = network_pktSampleSize / networkFormat_perSampleSize;
else
setNetworkFormatCodec ();
if (networkFormat_org != networkFormat)
cpLog (LOG_DEBUG, " networkFormat corrected to %d", networkFormat); if (network_pktSampleSize_org != network_pktSampleSize)
cpLog (LOG_DEBUG, " Number of network_pktSampleSize corrected to %d", network_pktSampleSize);
if (networkFormat_payloadSize_org != networkFormat_payloadSize)
cpLog (LOG_DEBUG, " Number of networkFormat_payloadSize corrected to %d", networkFormat_payloadSize);
}
//For dynamic payload type, setApiFormat the same as NetworkFormat
if ((apiFormat != p->getPayloadType()) &&
(p->getPayloadType() >= rtpPayloadDynMin) &&
(p->getPayloadType() <= rtpPayloadDynMax))
{
setApiFormat( p->getPayloadType(),
network_pktSampleSize,
0, p);
}
inPos = 0;
playPos = 0;
// set timing information
prevRtpTime = p->getRtpTime() - api_pktSampleSize;
prevPacketRtpTime = p->getRtpTime() - network_pktSampleSize;
prevNtpTime = rtp2ntp(p->getRtpTime()) - network_pktSampleSize * 1000 / networkFormat_clockRate;
prevSeqRecv = p->getSequence() - 1;
prevSeqPlay = p->getSequence() - 1;
recvCycles = 0;
playCycles = 0;
transit = 0;
jitter = 0;
jitterTime = jitterSeed;
// set up next gotime
gotime = rtp2ntp (p->getRtpTime()) + jitterTime;
}
void RtpReceiver::removeSource (RtpSrc s, int flag)
{
if (s != ssrc)
cpLog(LOG_DEBUG_STACK, "Removing non active source: %u", s);
// no longer listen to this source
probationSet = true;
srcProbation = s;
// no transmitter
sourceSet = false;
ssrc = 0;
probation = -2;
// remove from RTCP receiver
if (rtcpRecv && !flag) rtcpRecv->removeTranInfo (s, 1);
cpLog (LOG_DEBUG_STACK, "Removing source: %u", s);
}
NtpTime RtpReceiver::rtp2ntp (RtpTime rtpTime)
{
NtpTime ntptime = seedNtpTime +
((rtpTime - seedRtpTime) * 1000 / apiFormat_clockRate);
return ntptime;
}
/* --- Session state functions ------------------------------------- */
void RtpReceiver::emptyNetwork ()
{
// 接受数据 ,但是不处理数据。//ZHAOSONG
/*
// set up network activit
fd_set netFD;
FD_ZERO (&netFD);
FD_SET (myStack->getSocketFD(), &netFD);
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
// create empty holder packet
RtpPacket* p = new RtpPacket (RECV_BUF);
assert (p);
// receive packets until no more activity
int len;
int selret = select (myStack->getSocketFD() + 1,
&netFD, NULL, NULL, &timeout);
while (selret > 0)
{
len = myStack->receive (p->getPacketData(), p->getPacketAlloc());
if (len <= 0) break;
FD_ZERO (&netFD);
FD_SET (myStack->getSocketFD(), &netFD);
selret = select (myStack->getSocketFD() + 1,
&netFD, NULL, NULL, &timeout);
}
delete p; p = NULL;
cpLog (LOG_DEBUG_STACK, "RtpReceiver: Done empty network queue");
*/
}
/* --- Private Information for RTCP -------------------------------- */
void RtpReceiver::setRTCPrecv (RtcpReceiver* s)
{
rtcpRecv = s;
}
void RtpReceiver::setApiFormat (RtpPayloadType newtype, int no_samples, int packetSize,
RtpPacket* p, bool print)
{
apiFormat = newtype;
api_pktSampleSize = no_samples;
apiFormat_perSampleSize = 1;
switch (newtype)
{
case rtpPayloadPCMU:
case rtpPayloadPCMA:
if (print) cpLog(LOG_DEBUG, "Setting api format to: PCMU %d", no_samples);
apiFormat_clockRate = 8000;
break;
case rtpPayloadL16_mono:
if (print) cpLog(LOG_DEBUG, "Setting api format to: L16 %d", no_samples);
apiFormat_clockRate = 44100;
apiFormat_perSampleSize = 2;
break;
case rtpPayloadG729:
if (print) cpLog(LOG_DEBUG, "Setting api format to: G729 %d", no_samples);
apiFormat_clockRate = 8000;
break;
case rtpPayloadH261:
apiFormat_clockRate = 90000;
break;
case rtpPayloadH263:
apiFormat_clockRate = 90000;
break;
case rtpPayloadG723:
apiFormat_clockRate = 8000;
break;
default:
cpLog(LOG_ERR, "apiFormat: codec(%d) at sampleSize(%d) packetSize(%d)",
(int)newtype, no_samples, packetSize);
apiFormat_clockRate = 8000;
}
if (p)
apiFormat_payloadSize = p->getPayloadUsage();
else
apiFormat_payloadSize = api_pktSampleSize * apiFormat_perSampleSize;
if( packetSize != 0 )
apiFormat_payloadSize = packetSize;
}
void RtpReceiver::setNetworkFormat (RtpPayloadType newtype, int no_samples, int packetSize,
RtpPacket* p, bool print)
{
networkFormat = newtype;
network_pktSampleSize = no_samples;
networkFormat_perSampleSize = 1;
switch (newtype)
{
case rtpPayloadPCMU:
case rtpPayloadPCMA:
if (print) cpLog(LOG_DEBUG, "Setting network format to: PCMU %d", no_samples);
networkFormat_clockRate = 8000;
break;
case rtpPayloadL16_mono:
if (print) cpLog(LOG_DEBUG, "Setting network format to: L16 %d", no_samples);
networkFormat_clockRate = 44100;
networkFormat_perSampleSize = 2;
break;
case rtpPayloadH261:
networkFormat_clockRate = 90000;
break;
case rtpPayloadH263:
networkFormat_clockRate = 90000;
break;
case rtpPayloadG723:
networkFormat_clockRate = 8000;
break;
default:
cpLog(LOG_ERR, "networkFormat: codec(%d) at sampleSize(%d) packetSize(%d)",
(int)newtype, no_samples, packetSize);
networkFormat_clockRate = 8000;
}
if (p)
networkFormat_payloadSize = p->getPayloadUsage();
else
networkFormat_payloadSize = network_pktSampleSize * networkFormat_perSampleSize;
if( packetSize != 0 )
networkFormat_payloadSize = packetSize;
}
void RtpReceiver::setCodecString(const char* codecStringInput)
{
strncpy(codecString, codecStringInput, strlen(codecStringInput) + 1);
cpLog(LOG_DEBUG, "set CodecString %s", codecString);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -