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

📄 rtptran.cpp

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

/****************************************************************************
 *  Defines
 */
#define ACCEPTABLE_SYNC_NOISE	3
#define STREAM_END_DELAY_RTP_TOLERANCE	500

/****************************************************************************
 *  Includes
 */
#include "hxtypes.h"
#include "hxassert.h"
#include "debug.h"
#include "hxcom.h"
#include "hxmarsh.h"
#include "hxstrutl.h"
#include "netbyte.h"
#include "hxengin.h"
#include "ihxpckts.h"
#include "hxsbuffer.h"
#include "hxcomm.h"
#include "hxmon.h"
#include "netbyte.h"
#include "hxstring.h"
#include "chxpckts.h"
#include "hxslist.h"
#include "hxmap.h"
#include "hxdeque.h"
#include "hxbitset.h"
#include "timebuff.h"
#include "timeval.h"
#include "tconverter.h"
#include "rtptypes.h"
#include "hxqosinfo.h"
#include "hxqossig.h"
#include "hxqos.h"
//#include "hxcorgui.h"

#include "ntptime.h"

#include "rtspif.h"
#include "rtsptran.h"
#include "rtptran.h"
#include "rtpwrap.h"	// Wrappers for PMC generated base classes
#include "basepkt.h"
#include "hxtbuf.h"
#include "transbuf.h"
#include "hxtick.h"
#include "random32.h"	// random32()
#include "pkthndlr.h"	// in rtpmisc for RTCP routine
#include "rtcputil.h"	// takes care of RTCP in RTP mode
#include "rtspmsg.h"
#include "hxprefs.h"	// IHXPreferences
#include "hxmime.h"
#include "hxcore.h"

#include "hxheap.h"
#ifdef PAULM_IHXTCPSCAR
#include "objdbg.h"
#endif

#ifdef _DEBUG
#undef HX_THIS_FILE		
static const char HX_THIS_FILE[] = __FILE__;
#endif

#include "bufnum.h"

#define MAX_STARTINFO_WAIT_TIME		20000		// in milliseconds
#define MIN_NUM_PACKETS_SCANNED_FOR_LIVE_START    5
#define MAX_NUM_PACKETS_GAPPED_FOR_LIVE_START	  1

static const UINT32 NORMAL_ACK_INTERVAL = 1000;        // 1/sec
static const UINT32 MINIMUM_ACK_INTERVAL = 200;        // wait 200msecs

static const UINT32 NORMAL_REPORT_INTERVAL = 5000;	// 1 per 5secs

static const UINT32 TRANSPORT_BUF_GROWTH_RATE  = 1000;
static const UINT32 LATENCY_REPORT_INTERVAL_MS = 1000;

static const UINT32 RTP_NAT_TIMEOUT = 15000; // Default timeout period


static UINT32 GetNATTimeout(IUnknown* pContext)
{
    UINT32 ret = RTP_NAT_TIMEOUT;

    IHXPreferences* pPrefs = NULL;
    
    if (pContext &&
	(HXR_OK == pContext->QueryInterface(IID_IHXPreferences, 
					    (void**)&pPrefs)))
    {
	IHXBuffer* pPrefBuf = NULL;
	
	if ((HXR_OK == pPrefs->ReadPref("UDPNATTimeout", pPrefBuf)) &&
	    pPrefBuf)
	{
	    int tmp = atoi((const char*)pPrefBuf->GetBuffer());

	    if (tmp >= 0)
	    {
		ret = (UINT32)tmp;
	    }

	    HX_RELEASE(pPrefBuf);
	}
        HX_RELEASE(pPrefs);
    }

    return ret;
}

/******************************************************************************
*   RTP RTP RTP RTP RTP 
******************************************************************************/

RTPBaseTransport::RTPBaseTransport(BOOL bIsSource)
    : RTSPTransport(bIsSource)
    , m_lRefCount(0)    
    , m_pBwMgrInput(0)    
    , m_pSyncServer(NULL)
    , m_streamNumber(0)
    , m_uFirstSeqNum(0)
    , m_ulFirstRTPTS(0)
    , m_bFirstSet(FALSE)
    , m_bWeakStartSync(FALSE)
    , m_lTimeOffsetHX(0)
    , m_lTimeOffsetRTP(0)
    , m_lOffsetToMasterHX(0)
    , m_lOffsetToMasterRTP(0)
    , m_lSyncOffsetHX(0)
    , m_lSyncOffsetRTP(0)
    , m_lNTPtoHXOffset(0)
    , m_bNTPtoHXOffsetSet(FALSE)
    , m_ulLastRTPTS(0)
    , m_ulLastHXTS(0)
    , m_ulLastRawRTPTS(0)
    , m_bLastTSSet(FALSE)
    , m_pRTCPTran(0)
    , m_pReportHandler(0)
    , m_ulBaseTS(0)
    , m_bHasMarkerRule(FALSE)
    , m_bHasRTCPRule(FALSE)
    , m_ulPayloadWirePacket(0)
    , m_bIsLive(FALSE)
    , m_ulExtensionSupport(0)
    , m_bSeqNoSet(FALSE)
    , m_bRTPTimeSet(FALSE)
    , m_bActive(TRUE)
    , m_pFirstPlayTime(NULL)
    , m_bWaitForStartInfo(TRUE)
    , m_bAbortWaitForStartInfo(FALSE)
    , m_bEmulatePVSession(FALSE)
    , m_pMBitHandler(NULL)
    , m_pQoSInfo(NULL)
    , m_bSSRCDetermined(FALSE)
    , m_ulSSRCDetermined(0)
    , m_cLSRRead(0)
    , m_cLSRWrite(0)
#ifdef RTP_MESSAGE_DEBUG
    , m_bMessageDebug(FALSE)
#endif	// RTP_MESSAGE_DEBUG
{
    m_wrapSequenceNumber = DEFAULT_WRAP_SEQ_NO;
}

RTPBaseTransport::~RTPBaseTransport()
{
    resetStartInfoWaitQueue();
}

STDMETHODIMP
RTPBaseTransport::QueryInterface(REFIID riid, void** ppvObj)
{
    if (IsEqualIID(riid, IID_IUnknown))
    {
        AddRef();
        *ppvObj = this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXSourceBandwidthInfo))
    {
        AddRef();
        *ppvObj = (IHXSourceBandwidthInfo*)this;
        return HXR_OK;
    }

    *ppvObj = NULL;
    return HXR_NOINTERFACE;
}

STDMETHODIMP_(UINT32)
RTPBaseTransport::AddRef()
{
    return InterlockedIncrement(&m_lRefCount);
}

STDMETHODIMP_(UINT32)
RTPBaseTransport::Release()
{
    if(InterlockedDecrement(&m_lRefCount) > 0)
    {
	return m_lRefCount;
    }
    delete this;
    return 0;
}

void
RTPBaseTransport::Done()
{
    HX_RELEASE(m_pQoSInfo);
    HX_RELEASE(m_pBwMgrInput);
    HX_RELEASE(m_pRTCPTran);
    HX_RELEASE(m_pPacketFilter);
    HX_RELEASE(m_pSyncServer);
    HX_DELETE(m_pFirstPlayTime);
}

HX_RESULT
RTPBaseTransport::init()
{
    // m_pReportHandler will be freed in RTCPBaseTransport::Done()...
    HX_ASSERT(!m_pReportHandler);
    m_pReportHandler =   
	new ReportHandler(m_bIsSource, !m_bIsSource, random32(HX_GET_TICKCOUNT()));    
    HX_ASSERT(m_pReportHandler);
    if(!m_pReportHandler)
    {
        return HXR_OUTOFMEMORY;
    }
    
#ifdef RTP_MESSAGE_DEBUG
    IHXPreferences* pPreferences = NULL;

    if (m_pContext &&
	(HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences,
					     (void**) &pPreferences)))
    {
	IHXBuffer* pBuffer = NULL;

	if (HXR_OK == pPreferences->ReadPref("RTPMessageDebug", pBuffer))
	{
	    m_bMessageDebug = atoi((const char*)pBuffer->GetBuffer()) ? TRUE : FALSE;
	    HX_RELEASE(pBuffer);
	    if (m_bMessageDebug)
	    {
		if (HXR_OK == pPreferences->ReadPref("RTPMessageDebugFile", pBuffer))
		{
		    if (pBuffer->GetSize() <= 0)
		    {
			// no file name, no log
			m_bMessageDebug = FALSE;
		    }
		    else
		    {
			m_messageDebugFileName = (const char*) pBuffer->GetBuffer();
		    }			
		}
                HX_RELEASE(pBuffer);
	    }
	}
    }

    HX_RELEASE(pPreferences);
#endif	// RTP_MESSAGE_DEBUG
    return HXR_OK;
}

void
RTPBaseTransport::addStreamInfo(RTSPStreamInfo* pStreamInfo, UINT32 ulBufferDepth)
{   
    RTSPTransport::addStreamInfo(pStreamInfo, ulBufferDepth);

    // there better be only one stream
    m_streamNumber = pStreamInfo->m_streamNumber;

    // if pStreamInfo->m_rtpPayloadType is -1, it hasn't been set
    // by user, so just assign RTP_PAYLOAD_RTSP
    if (pStreamInfo->m_rtpPayloadType < 0)
    {
	m_rtpPayloadType = RTP_PAYLOAD_RTSP;
    }
    else
    {
	m_rtpPayloadType = (UINT8)pStreamInfo->m_rtpPayloadType;
    }	

    if (pStreamInfo)
    {
	if (pStreamInfo->m_bHasMarkerRule)
	{
	    m_bHasMarkerRule = pStreamInfo->m_bHasMarkerRule;
	    m_markerRuleNumber = pStreamInfo->m_markerRule;
	    // better be odd.
	    HX_ASSERT(m_markerRuleNumber & 0x1);
	}
	
    	m_bIsLive = pStreamInfo->m_bIsLive;
    	m_ulExtensionSupport = pStreamInfo->m_bExtensionSupport;
    	m_bActive = pStreamInfo->m_bActive;
	m_bIsSyncMaster = pStreamInfo->m_bIsSyncMaster;

	// RTP transport always creates RTP packets on reception
	if (!m_bIsSource)
	{
	    RTSPStreamData* pStreamData = NULL;

	    pStreamData = m_pStreamHandler->getStreamData(pStreamInfo->m_streamNumber);

	    HX_ASSERT(pStreamData);

	    if (pStreamData)
	    {
		pStreamData->m_bUsesRTPPackets = TRUE;
	    }

	    if (pStreamData->m_pTSConverter)
	    {
		m_pRTCPTran->SetTSConverter(
		    pStreamData->m_pTSConverter->GetConversionFactors());
	    }
	}
	
    	/*
    	 *  Reflection support
    	 */
    	m_bHasRTCPRule = pStreamInfo->m_bHasRTCPRule;
    	if (m_bHasRTCPRule)
    	{
    	    m_RTCPRuleNumber = pStreamInfo->m_RTCPRule;
    	}
	m_ulPayloadWirePacket = pStreamInfo->m_ulPayloadWirePacket;

	if (m_pRTCPTran)
	{
	    m_pRTCPTran->addStreamInfo(pStreamInfo, ulBufferDepth);
	}
    }
}

/*
*  We need to set an initial SeqNo & timestamp for RTP
*/

HX_RESULT
RTPBaseTransport::setFirstSeqNum(UINT16 uStreamNumber, UINT16 uSeqNum)
{
    HX_RESULT theErr = HXR_UNEXPECTED;

    // On client we allow setting of sequence number only once not to cause
    // havoc in transport buffer
    if (m_bIsSource || (!m_bSeqNoSet))
    {
	theErr = RTSPTransport::setFirstSeqNum(uStreamNumber, uSeqNum);

#ifdef RTP_MESSAGE_DEBUG
	messageFormatDebugFileOut("INIT: StartSeqNum=%u", 
				  uSeqNum);
#endif	// RTP_MESSAGE_DEBUG

	if (SUCCEEDED(theErr))
	{
	    m_bSeqNoSet = TRUE;
	}
    }
    
    return theErr;
}

void
RTPBaseTransport::setFirstTimeStamp(UINT16 uStreamNumber, UINT32 ulTS, 
                                    BOOL bIsRaw)
{
    RTSPStreamData* pStreamData = 
	m_pStreamHandler->getStreamData(uStreamNumber);

    if (pStreamData)
    {
	if (m_bIsSource)
	{	    	
	    /* ulFrom is what we want to put in RTP-Info: rtptimestamp */
	    if (pStreamData->m_pTSConverter && !bIsRaw)
	    {
		pStreamData->m_lastTimestamp = pStreamData->m_pTSConverter->hxa2rtp(ulTS);
	    }
	    else
	    {
		pStreamData->m_lastTimestamp = ulTS;
	    }
	}
	else if (!m_bRTPTimeSet)
	{
	    // ulTS is what's reported in rtptime of RTP-Info PLAY response 
	    // header in RTP time.  Unit is RTP.
	    /*
	     *	HXTimeval = PktTime*Factor - (ulTS*Factor - m_ulPlayRangeFrom)
	     *  RTPTimeval = PktTime - (ulTS - m_ulPlayRangeFrom / Factor)
	     */	    
            if (m_ulPlayRangeFrom != RTSP_PLAY_RANGE_BLANK)
            {
	        if (pStreamData->m_pTSConverter)
	        {
		    m_lTimeOffsetRTP = ulTS -
				       pStreamData->
					    m_pTSConverter->hxa2rtp_raw(m_ulPlayRangeFrom);
		    pStreamData->m_pTSConverter->setAnchor(m_ulPlayRangeFrom, ulTS);
		    m_lTimeOffsetHX = 0;
	        }
	        else
	        {
		    m_lTimeOffsetHX = m_lTimeOffsetRTP = ulTS - m_ulPlayRangeFrom;		
	        }
            }

	    if ((m_ulPlayRangeFrom != RTSP_PLAY_RANGE_BLANK) &&
		(m_ulPlayRangeTo != RTSP_PLAY_RANGE_BLANK))
	    {
		pStreamData->m_pTransportBuffer->InformTimestampRange(
		    m_ulPlayRangeFrom,
		    m_ulPlayRangeTo,
		    STREAM_END_DELAY_RTP_TOLERANCE);
	    }

#ifdef RTP_MESSAGE_DEBUG
	    messageFormatDebugFileOut("INIT: RTPOffset=%u HXOffset=%u", 
				      m_lTimeOffsetRTP, 
				      m_lTimeOffsetHX);
#endif	// RTP_MESSAGE_DEBUG

	    // Reset the time stamp ordering
	    HX_DELETE(pStreamData->m_pTSOrderHack);
	}	

	m_bRTPTimeSet = TRUE;
    }
}

void
RTPBaseTransport::notifyEmptyRTPInfo(void)
{
    // If RTP-Info is empty there is no point in waiting for out-of-band
    // start info (start seq number and time stamp) since this is the
    // only out-of-band method of communicating start info. in RTP.
    m_bAbortWaitForStartInfo = TRUE;
}

void 
RTPBaseTransport::setPlayRange(UINT32 ulFrom, UINT32 ulTo)
{
    // this is the Range values in PLAY request in RMA time (ms) called on PLAY 
    // request
    RTSPTransport::setPlayRange(ulFrom, ulTo);
    
    m_bSeqNoSet = FALSE;
    m_bRTPTimeSet = FALSE;
    m_bWaitForStartInfo = TRUE;
    m_bAbortWaitForStartInfo = FALSE;
    m_uFirstSeqNum = 0;
    m_ulFirstRTPTS = 0;
    m_bFirstSet = FALSE;
    m_bWeakStartSync = FALSE;
    m_lTimeOffsetHX = 0;
    m_lTimeOffsetRTP = 0;
    m_lOffsetToMasterHX = 0;
    m_lOffsetToMasterRTP = 0;
    m_lSyncOffsetHX = 0;
    m_lSyncOffsetRTP = 0;
    m_ulLastRTPTS = 0;
    m_ulLastHXTS = 0;
    m_ulLastRawRTPTS = 0;
    m_bLastTSSet = FALSE;
    m_lNTPtoHXOffset = 0;
    m_bNTPtoHXOffsetSet = FALSE;
    resetStartInfoWaitQueue();

#ifdef RTP_MESSAGE_DEBUG
    messageFormatDebugFileOut("INIT: PlayRange=%u-%u", 
			       ulFrom, ulTo);
#endif	// RTP_MESSAGE_DEBUG
}

HX_RESULT
RTPBaseTransport::setFirstPlayTime(Timeval* pTv)
{
    if (!m_pFirstPlayTime)
    {
	m_pFirstPlayTime = new Timeval();
        if(!m_pFirstPlayTime)
        {
            return HXR_OUTOFMEMORY;
        }
    }
    
    m_pFirstPlayTime->tv_sec = pTv->tv_sec;
    m_pFirstPlayTime->tv_usec = pTv->tv_usec;
    return HXR_OK;
}

HX_RESULT

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -