📄 rtcputil.cpp
字号:
/*
* Increment item byte count for null termination
*/
unByteCount++;
// Align on word boundary
// RTCP pkt length is in 32-bits word!
unByteCount += (unByteCount % 4) ? 4 - (unByteCount % 4) : 0;
HX_ASSERT(unByteCount % 4 == 0);
// I am counting 32-bits word
pPkt->length = (unByteCount / 4); // count of words - 1
//one more 32-bits for SSRC
pPkt->length++;
return HXR_OK;
}
HX_RESULT
ReportHandler::MakeBye(RTCPPacket* pPkt)
{
HX_ASSERT(m_pSenderMe || m_pReceiverMe);
HX_ASSERT(pPkt);
pPkt->version_flag = 0x02;
pPkt->padding_flag = 0;
pPkt->packet_type = RTCP_BYE;
pPkt->length = 1; // len in 32-bits words minus one
pPkt->count = 1;
// use access function
if (m_pSenderMe)
{
pPkt->SetByeSrc(&m_pSenderMe->m_ulSsrc, pPkt->count);
#ifdef DUMP_REPORTS
printf("BYE %u:\n", m_pSenderMe->m_ulSsrc);
#endif
}
else
{
pPkt->SetByeSrc(&m_pReceiverMe->m_ulSsrc, pPkt->count);
#ifdef DUMP_REPORTS
printf("BYE %u\n", m_pReceiverMe->m_ulSsrc);
#endif
}
#ifdef DUMP_REPORTS
fflush(stdout);
#endif
return HXR_OK;
}
/*
* for now this is the only APP.
*/
HX_RESULT
ReportHandler::MakeEOSApp(RTCPPacket* pPkt)
{
HX_ASSERT(m_pSenderMe);
HX_ASSERT(pPkt);
pPkt->version_flag = 0x02;
pPkt->padding_flag = 0;
pPkt->packet_type = RTCP_APP;
pPkt->app_ssrc = m_pSenderMe->m_ulSsrc;
pPkt->count = 1;
pPkt->length = 4; // 2 + the length of APPItem...fortunately, we don't
// have to align them
memcpy(pPkt->app_name, "RNWK", 4); /* Flawfinder: ignore */
// this is application dependent...
APPItem item;
item.app_type = APP_EOS;
item.seq_no = m_pSenderMe->m_unLastSeqNo;
item.packet_sent = (UINT8)m_pSenderMe->m_ulNumPktSentSoFar ? 1 : 0;
item.timestamp = m_pSenderMe->m_ulLastRTPTimestamp;
pPkt->SetAPPItem(&item, pPkt->count);
return HXR_OK;
}
HX_RESULT
ReportHandler::MakeBufInfoApp(RTCPPacket* pPkt,
UINT32 ulLowTS, UINT32 ulHighTS,
UINT32 ulBytesBuffered)
{
HX_RESULT res = HXR_UNEXPECTED;
if (pPkt)
{
pPkt->version_flag = 0x02;
pPkt->padding_flag = 0;
pPkt->packet_type = RTCP_APP;
pPkt->count = 1;
pPkt->app_ssrc = m_pReceiverMe->m_ulSsrc;
memcpy(pPkt->app_name, "HELX", 4);
pPkt->length = 2;
APPItem item;
item.app_type = APP_BUFINFO;
item.lowest_timestamp = ulLowTS;
item.highest_timestamp = ulHighTS;
item.bytes_buffered = ulBytesBuffered;
item.padding0 = 0;
pPkt->SetAPPItem(&item, 1);
pPkt->length += 4;
res = HXR_OK;
}
return res;
}
ReceiverInfo*
ReportHandler::GetOrCreateReceiverInfo(UINT32 ulSsrc)
{
ReceiverInfo* pReceiver = NULL;
if (!m_mapReceivers.Lookup(ulSsrc, (void*&)pReceiver))
{
#ifdef DUMP_MEMBER_COUNT
printf("New Receiver (#%u): %u\n", m_mapReceivers.GetCount()+1, ulSsrc);
fflush(stdout);
#endif
// doesn't exist, create one.
pReceiver = new ReceiverInfo;
if (!pReceiver)
{
return NULL;
}
m_mapReceivers.SetAt(ulSsrc, (void*)pReceiver);
#if _DEBUG
ReceiverInfo* pTmp = NULL;
HX_ASSERT(m_mapReceivers.Lookup(ulSsrc, (void*&)pTmp));
HX_ASSERT(pTmp);
#endif
}
HX_ASSERT(pReceiver);
return pReceiver;
}
void
ReportHandler::DeleteReceiverInfo(UINT32 ulSsrc)
{
/* since we need to do timeout, we might as well do the right thing for
* this as well....mark as delete, and delete after a fixed timeout...so,
* we know we don't receive any late pkt after we delete this entry...
*/
ReceiverInfo* pReceiver = NULL;
if (m_mapReceivers.Lookup(ulSsrc, (void*&)pReceiver))
{
#ifdef DUMP_MEMBER_COUNT
printf("Deleteing Receiver: %u\n", ulSsrc);
fflush(stdout);
#endif
HX_ASSERT(pReceiver);
m_mapReceivers.RemoveKey(ulSsrc);
delete pReceiver;
}
}
ReceptionInfo*
ReportHandler::GetOrCreateReceptionInfo(UINT32 ulSsrc)
{
ReceptionInfo* pRInfo = NULL;
if (!m_mapSenders.Lookup(ulSsrc, (void*&)pRInfo))
{
#ifdef DUMP_MEMBER_COUNT
printf("New Sender (#%u): %u\n", m_mapSenders.GetCount()+1, ulSsrc);
fflush(stdout);
#endif
// doesn't exist, create one.
pRInfo = new ReceptionInfo();
if (!pRInfo)
{
return NULL;
}
// pRInfo->m_ulProbation = m_ulDefaultProbation;
m_mapSenders.SetAt(ulSsrc, (void*)pRInfo);
#if _DEBUG
ReceptionInfo* pTmp = NULL;
HX_ASSERT(m_mapSenders.Lookup(ulSsrc, (void*&)pTmp));
HX_ASSERT(pTmp);
#endif
}
HX_ASSERT(pRInfo);
return pRInfo;
}
void
ReportHandler::DeleteReceptionInfo(UINT32 ulSsrc)
{
/* since we need to do timeout, we might as well do the right thing for
* this as well....mark as delete, and delete after a fixed timeout...so,
* we know we don't receive any late pkt after we delete this entry...
*/
ReceptionInfo* pRInfo= NULL;
if (m_mapSenders.Lookup(ulSsrc, (void*&)pRInfo))
{
#ifdef DUMP_MEMBER_COUNT
printf("Deleteing Sender: %u\n", ulSsrc);
fflush(stdout);
#endif
HX_ASSERT(pRInfo);
m_mapSenders.RemoveKey(ulSsrc);
delete pRInfo;
}
}
/*
*/
double
ReportHandler::GetRTCPInterval()
{
// include myself
double interval =
rtcp_interval(m_mapReceivers.GetCount() + 1,
m_pSenderMe ? m_mapSenders.GetCount()+1 : m_mapSenders.GetCount(),
m_ulRSByteRate,
m_ulRRByteRate,
m_pSenderMe ? m_pSenderMe->m_bWeSent : 0,
m_ulAvgRTCPSize,
m_bInitialIntervalCalc,
m_minRTCPInterval);
m_bInitialIntervalCalc = FALSE;
return interval;
}
void ReportHandler::SetRTCPIntervalParams(UINT32 ulRSBitRate,
UINT32 ulRRBitRate,
UINT32 ulMinRTCPIntervalMs)
{
m_ulRSByteRate = ulRSBitRate >> 3; // bitrate -> byterate
m_ulRRByteRate = ulRRBitRate >> 3; // bitrate -> byterate
m_minRTCPInterval = ((double)ulMinRTCPIntervalMs) / 1000.0; // ms -> sec
}
/*
* ReceptionInfo Func's
*/
void
ReceptionInfo::InitSeqNo(UINT16 unSeqNo)
{
#ifdef _DEBUG
HX_ASSERT(INIT == m_state);
m_state = UPDATE;
#endif
// m_ulBaseSeqNo = unSeqNo - 1;
m_ulBaseSeqNo = unSeqNo;
m_unMaxSeqNo = unSeqNo;
m_ulBadSeqNo = RTP_SEQ_MOD + 1;
m_ulCycles = 0;
m_ulNumPktReceived = 0;
m_ulExpectedPrior = 0;
m_ulReceivedPrior = 0;
}
BOOL
ReceptionInfo::UpdateSeqNo(UINT16 unSeqNo)
{
#ifdef _DEBUG
HX_ASSERT(UPDATE == m_state);
#endif
UINT16 unDelta = unSeqNo - m_unMaxSeqNo;
#if 0 /* don't ever throu pkt away! */
if (m_ulProbation)
{
if (unSeqNo == m_unMaxSeqNo + 1)
{
// pkt is in sequence
m_ulProbation--;
m_unMaxSeqNo = unSeqNo;
if (0 == m_ulProbation)
{
InitSeqNo(unSeqNo);
m_ulNumPktReceived++;
return TRUE;
}
}
else
{
// pkt is NOT in sequence
m_ulProbation = MIN_SEQUENTIAL - 1;
m_unMaxSeqNo = unSeqNo;
}
return FALSE;
}
else
#endif
if (unDelta < MAX_DROPOUT)
{
// in order, with permissible gap
if (unSeqNo < m_unMaxSeqNo)
{
// seq# wrapped - count another 64k cycle
m_ulCycles += RTP_SEQ_MOD;
}
m_unMaxSeqNo = unSeqNo;
}
else if (unDelta <= RTP_SEQ_MOD - MAX_MISORDER)
{
// seq# made a very large jump
if (unSeqNo == m_ulBadSeqNo)
{
// two sequential pkts -- assume that the other side
// restarted w/o telling us, so just re-sync
// (i.e., pretned this was the first pkt)
InitSeqNo(unSeqNo);
}
else
{
m_ulBadSeqNo = (unSeqNo + 1) & (RTP_SEQ_MOD - 1);
// (i.e. m_ulBadSeq = unSeq + 1;)
return FALSE;
}
}
else
{
/* duplicate or reordered packet */
}
m_ulNumPktReceived++;
return TRUE;
}
void
ReceptionInfo::MakeReceptionReport(UINT32 ulSsrc, REF(ReceptionReport) rr, UINT32 ulNow)
{
#ifdef DUMP_REPROTS
printf("making rr for %u\n", ulSsrc);
fflush(stdout);
#endif
// ssrc of a sender that we are reporting
rr.ssrc = ulSsrc;
/* extended last seqno received */
rr.last_seq = m_ulCycles + m_unMaxSeqNo;
/* simply #pkt expected - received */
UINT32 ulExpected = rr.last_seq - m_ulBaseSeqNo + 1;
rr.lost = ulExpected - m_ulNumPktReceived;
UINT32 ulExpectedInterval = ulExpected - m_ulExpectedPrior;
UINT32 ulReceivedInterval = m_ulNumPktReceived - m_ulReceivedPrior;
INT32 lLostInterval = ulExpectedInterval - ulReceivedInterval;
// save them for the next time
m_ulExpectedPrior = ulExpected;
m_ulReceivedPrior = m_ulNumPktReceived;
/*
* The resulting fraction is an 8-bit fixed point number with the binary
* point at the left edge.
*/
if (0 == ulExpectedInterval || lLostInterval <= 0)
{
rr.fraction = 0;
}
else
{
rr.fraction = (UINT8)((lLostInterval << 8) / ulExpectedInterval);
}
rr.jitter = m_ulJitter >> 4;
rr.lsr = m_ulLSR ? m_ulLSR : 0;
/* expressed in 1/65536 sec...ahhh...make it 66 */
rr.dlsr = (m_ulLastSRReceived ?
CALCULATE_ELAPSED_TICKS(m_ulLastSRReceived, ulNow) :
0 /* SR not yet received */) * 66;
#ifdef DUMP_REPROTS
printf("\tssrc: %u\n", rr.ssrc);
printf("\tlast_seq: %u\n", rr.last_seq);
printf("\tlost: %u\n", rr.lost);
printf("\tfraction: %u\n", rr.fraction);
printf("\tjitter: %u\n", rr.jitter);
printf("\tlsr: %u\n", rr.lsr);
printf("\tdlsr: %u\n", rr.dlsr);
fflush(stdout);
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -