📄 rtcputil.cpp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#include "hxtypes.h"
#include "hxcom.h"
#include "hlxclib/string.h"
#include "rtpwrap.h"
#include "hxtick.h"
#include "hxengin.h"
#include "tconverter.h"
#include "interval.h"
#include "ntptime.h"
#include "rtcputil.h"
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
//#define DUMP_REPORTS
//#define DUMP_RECEIVE_REPORTS
//#define DUMP_MEMBER_COUNT
/* Used in UpdateSeqNo */
const UINT32 MAX_DROPOUT = 3000;
const UINT32 MAX_MISORDER = 100;
const UINT32 MIN_SEQUENTIAL = 2;
const UINT32 RTP_SEQ_MOD = (1 << 16);
//ReportHandler::ReportHandler(BOOL bIsSender, BOOL bIsReceiver, UINT32 ulSsrc, UINT32 ulDefaultProbation)
ReportHandler::ReportHandler(BOOL bIsSender, BOOL bIsReceiver, UINT32 ulSsrc)
: m_pSenderMe(NULL)
, m_ulMySsrc(ulSsrc)
, m_pReceiverMe(NULL)
// , m_ulDefaultProbation(ulDefaultProbation)
, m_ulAvgRTCPSize(128)
, m_bInitialIntervalCalc(TRUE)
, m_pNTPBase(NULL)
, m_nRTPTSBase(0)
, m_pTSConverter(NULL)
{
/* it is "either or" in RealSystem */
HX_ASSERT((bIsSender || bIsReceiver) && !(bIsSender && bIsReceiver));
if (bIsSender)
{
m_pSenderMe = new MyselfAsSender();
m_pSenderMe->m_ulSsrc = ulSsrc;
}
else
{
m_pReceiverMe = new MyselfAsReceiver();
m_pReceiverMe->m_ulSsrc = ulSsrc;;
}
}
ReportHandler::~ReportHandler()
{
CHXMapLongToObj::Iterator i;
for (i = m_mapReceivers.Begin(); i != m_mapReceivers.End(); ++i)
{
delete (ReceiverInfo*)(*i);
}
for (i = m_mapSenders.Begin(); i != m_mapSenders.End(); ++i)
{
delete (ReceptionInfo*)(*i);
}
HX_DELETE(m_pSenderMe);
HX_DELETE(m_pReceiverMe);
HX_DELETE(m_pNTPBase);
HX_DELETE(m_pTSConverter);
}
void
ReportHandler::Init(REF(Timeval) tvInitial,
INT64 nInitialRTP,
CHXTimestampConverter* pConverter)
{
HX_ASSERT(!m_pNTPBase && "Are you sure to reset this?");
HX_DELETE(m_pNTPBase);
HX_DELETE(m_pTSConverter);
m_pNTPBase = new NTPTime(tvInitial);
m_nRTPTSBase = nInitialRTP;
if (pConverter)
{
m_pTSConverter = new CHXTimestampConverter();
*m_pTSConverter = *pConverter;
}
}
void
ReportHandler::OnRTPReceive(UINT32 ulSsrc, UINT16 unSeqNo,
UINT32 ulHXTimestamp, UINT32 ulNow)
{
HX_ASSERT(m_pReceiverMe && !m_pSenderMe);
ReceptionInfo* pRInfo = GetOrCreateReceptionInfo(ulSsrc);
pRInfo->m_bHeardSinceLastTime = TRUE;
// in the same unit
INT32 lTransit = ulNow - ulHXTimestamp;
if (0 == pRInfo->m_ulNumPktReceived)
{
pRInfo->InitSeqNo(unSeqNo);
/* so it won't be some crazy number */
pRInfo->m_ulTransit = lTransit;
}
// all updates will be done here.
pRInfo->UpdateSeqNo(unSeqNo);
/************************
* calculate jitter (rfc 1889 Appendix A.8)
* this doesn't belong to UpdateSeqNo() so just do it here...
*/
INT32 lDiff = lTransit - pRInfo->m_ulTransit;
pRInfo->m_ulTransit = lTransit;
if (lDiff < 0)
{
lDiff = -lDiff;
}
pRInfo->m_ulJitter += lDiff - ((pRInfo->m_ulJitter + 8) >> 4);
}
void
ReportHandler::OnRTCPReceive(RTCPPacket* pPkt, UINT32 ulNow)
{
HX_ASSERT(m_pSenderMe || m_pReceiverMe);
#ifdef DUMP_RECEIVE_REPORTS
printf("\n%u", pPkt->packet_type);
#endif
if (RTCP_SR == pPkt->packet_type)
{
HX_ASSERT(m_pReceiverMe);
// it IS possible to get RTCP before RTP if this is multicast.
ReceptionInfo* pRInfo = GetOrCreateReceptionInfo(pPkt->sr_ssrc);
// the middle 32 bits out of 64 in the NTP timestamp
pRInfo->m_ulLSR = pPkt->ntp_sec << 16;
pRInfo->m_ulLSR |= (pPkt->ntp_frac >> 16);
pRInfo->m_ulLastSRReceived = ulNow;
pRInfo->m_bHeardSinceLastTime = TRUE;
#ifdef DUMP_RECEIVE_REPORTS
printf("\tSR %u:\n", pPkt->sr_ssrc);
printf("\t\trtp_ts: %u\n", pPkt->rtp_ts);
printf("\t\tntp: %u: %u\n", pPkt->ntp_sec, pPkt->ntp_frac);
printf("\t\tpsent: %u osent: %u\n", pPkt->psent, pPkt->osent);
fflush(stdout);
#endif
}
else if (RTCP_RR == pPkt->packet_type)
{
// just need to keep track of them. Ignore the returned value...
GetOrCreateReceiverInfo(pPkt->rr_ssrc);
#ifdef DUMP_RECEIVE_REPORTS
printf("\tRR %u\n", pPkt->rr_ssrc);
for (UINT32 i = 0; i < pPkt->count; i++)
{
ReceptionReport rr = pPkt->rr_data[i];
printf("\t\tssrc: %u\n", rr.ssrc);
printf("\t\tlast_seq: %u\n", rr.last_seq);
printf("\t\tlost: %u\n", rr.lost);
printf("\t\tfraction: %u\n", rr.fraction);
printf("\t\tjitter: %u\n", rr.jitter);
printf("\t\tlsr: %u\n", rr.lsr);
printf("\t\tdlsr: %u\n", rr.dlsr);
}
fflush(stdout);
#endif
}
else if (RTCP_BYE == pPkt->packet_type)
{
UINT32 ulSsrc;
for (UINT32 i = 0; i < pPkt->count; i++)
{
ulSsrc = *(pPkt->bye_src + i);
// remove this entry
DeleteReceiverInfo(ulSsrc);
DeleteReceptionInfo(ulSsrc);
}
}
#ifdef DUMP_RECEIVE_REPORTS
else if (RTCP_SDES == pPkt->packet_type)
{
printf("\tSDES\n");
SDESItem* pItem = NULL;
CHXSimpleList* pSdesList = NULL;
CHXSimpleList::Iterator j;
CHXMapLongToObj::Iterator i;
for (i = pPkt->m_mapSDESSources.Begin(); i != pPkt->m_mapSDESSources.End(); ++i)
{
pSdesList = (CHXSimpleList*)(*i);
for (j = pSdesList->Begin(); j != pSdesList->End(); ++j)
{
pItem = (SDESItem*)(*j);
printf("\t\ttype %u: %s\n", pItem->sdes_type, pItem->data);
}
}
}
printf("\n");
fflush(stdout);
#endif
}
HX_RESULT
ReportHandler::MakeSR(RTCPPacket* pPkt, UINT32 ulNow)
{
Timeval tvNow((INT32)(ulNow / 1000), (INT32)(ulNow % 1000 * 1000));
return MakeSR(pPkt, tvNow);
}
HX_RESULT
ReportHandler::MakeSR(RTCPPacket* pPkt, REF(Timeval) tvNow)
{
HX_ASSERT(m_pSenderMe);
HX_ASSERT(pPkt);
if (!m_pSenderMe->m_bWeSent)
{
// no pkt has been sent, wait!
return HXR_UNEXPECTED;
}
pPkt->version_flag = 0x02;
pPkt->padding_flag = 0;
pPkt->packet_type = RTCP_SR;
pPkt->sr_ssrc = m_pSenderMe->m_ulSsrc;
pPkt->psent = m_pSenderMe->m_ulNumPktSentSoFar;
pPkt->osent = m_pSenderMe->m_ulNumByteSentSoFar;
/* since a sender is never a receiver */
pPkt->count = 0;
pPkt->sr_data = NULL;
pPkt->length = 6;
/* NTP time when this report is generated */
NTPTime ntpNow(tvNow);
/*
* RTP TS that corresponds to NTP time above
* m_pNTPBase and m_nRTPTSBase are the same time in diff unit
*/
INT64 nRTPNow = m_nRTPTSBase;
if (m_pTSConverter)
{
nRTPNow += m_pTSConverter->hxa2rtp((UINT32)(ntpNow - *m_pNTPBase));
}
else
{
nRTPNow += (UINT32)(ntpNow - *m_pNTPBase);
}
HX_ASSERT(nRTPNow >= 0);
// NTP
pPkt->ntp_sec = ntpNow.m_ulSecond;
pPkt->ntp_frac = ntpNow.m_ulFraction;
// RTP
pPkt->rtp_ts = INT64_TO_UINT32(nRTPNow);
#ifdef DUMP_REPORTS
printf("SR %u:\n", pPkt->sr_ssrc);
printf("\trtp_ts: %u\n", pPkt->rtp_ts);
printf("\tntp: %u: %u\n", pPkt->ntp_sec, pPkt->ntp_frac);
printf("\tpsent: %u osent: %u\n", pPkt->psent, pPkt->osent);
fflush(stdout);
#endif
return HXR_OK;
}
/*
* Make RR. We need this even if there is no reception report
*/
HX_RESULT
ReportHandler::MakeRR(RTCPPacket* pPkt, UINT32 ulNow)
{
// Timeval tvNow((INT32)(ulNow / 1000), (INT32)(ulNow % 1000 * 1000));
// return MakeRR(pPkt, tvNow);
HX_ASSERT(m_pReceiverMe);
HX_ASSERT(pPkt);
pPkt->version_flag = 0x02;
pPkt->padding_flag = 0;
pPkt->packet_type = RTCP_RR;
pPkt->rr_ssrc = m_pReceiverMe->m_ulSsrc;
// can't be more than this
ReceptionReport* pRr = new ReceptionReport[m_mapSenders.GetCount()];
if (!pRr)
{
return HXR_OUTOFMEMORY;
}
#ifdef DUMP_REPORTS
printf("RR %u:\n", pPkt->rr_ssrc);
#endif
UINT8 chRRCount = 0;
ReceptionInfo* pRInfo = NULL;
CHXMapLongToObj::Iterator i;
for (i = m_mapSenders.Begin(); i != m_mapSenders.End(); ++i)
{
pRInfo = (ReceptionInfo*)(*i);
if (pRInfo->m_bHeardSinceLastTime)
{
// need to make a report for this sender
pRInfo->MakeReceptionReport(i.get_key(), pRr[chRRCount++], ulNow);
pRInfo->m_bHeardSinceLastTime = FALSE;
}
}
pPkt->count = chRRCount;
pPkt->length = 1 + 6 * (UINT16)pPkt->count;
pPkt->SetReceiverReport(pRr, pPkt->count);
// SetReceiverReport is making a copy.
HX_VECTOR_DELETE(pRr);
return HXR_OK;
}
/*
* CNAME is the only one required
*/
HX_RESULT
ReportHandler::MakeSDES(RTCPPacket* pPkt, const BYTE* pcCNAME)
{
HX_ASSERT(m_pSenderMe || m_pReceiverMe);
HX_ASSERT(pPkt);
HX_ASSERT(pcCNAME);
pPkt->version_flag = 0x02;
pPkt->padding_flag = 0;
pPkt->packet_type = RTCP_SDES;
pPkt->count = 1;
UINT16 unByteCount = 0;
SDESItem item;
item.sdes_type = SDES_CNAME;
item.length = strlen((const char*)pcCNAME);
item.data = (BYTE*)pcCNAME;
if (m_pSenderMe)
{
pPkt->AddSDESItem(m_pSenderMe->m_ulSsrc, item);
}
else
{
pPkt->AddSDESItem(m_pReceiverMe->m_ulSsrc, item);
}
// 2 for sdes_type and length
unByteCount += item.length + 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -