⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtcputil.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* ***** 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 + -