www.pudn.com > rtp实现协议占.rar > rtptran.h


/* ***** 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 ***** */ 

#ifndef _RTPTRAN_H_
#define _RTPTRAN_H_

// #define RTP_MESSAGE_DEBUG

#include "hxengin.h"
#include "hxmon.h"
#include "transbuf.h"
#include "statinfo.h"
#include "hxsmbw.h"
#include "ntptime.h"
#include "tconverter.h"
#include "chxkeepalive.h"

// GCC won't let me forward declare CHXMapLongToObj::Iterator, 
// so I have to include this. -JR
#include "hxmap.h"
#include "hxslist.h"
#include "hxqossig.h"
#include "hxqos.h"

#include "packfilt.h"

struct IHXQoSTransportAdaptationInfo;
struct IHXScheduler;
struct IHXUDPSocket;
struct IHXPacket;
struct IHXBuffer;
struct IHXCommonClassFactory;
struct IHXInternalReset;
struct IHXPlayerState;
struct IHXAccurateClock;
class  RTSPResendBuffer;
class  CHXBitset;
class  HX_deque;
class  Timeval;
class  CHXTimestampConverter;

class RTCPBaseTransport;
class RTCPUDPTransport;
class RTCPTCPTransport;
class RTCPPacket;
class ReportHandler;

_INTERFACE IHXQoSSignal;
_INTERFACE IHXQoSSignalBus;
_INTERFACE IHXQoSSignalSourceResponse;

HX_RESULT
FixRTPHeader(IHXCommonClassFactory* pCCF, 
	     IHXBuffer* pOrigBuf, 
	     REF(IHXBuffer*) pNewBuf, 
	     UINT16 unSeqNoOffset, 
	     UINT32 ulRTPTSOffset);
	     
HX_RESULT
FixRTCPSR(IHXCommonClassFactory* pCCF, 
	  IHXBuffer* pOrigBuf, 
	  REF(IHXBuffer*) pNewBuf, 
	  UINT32 ulRTPTSOffset);

/* The largest number of SR records we will keep */
#define LSR_HIST_SZ 64

#define RTP_FILTER_CONSTANT 3

struct LSRRecord
{
    UINT32          m_ulSourceLSR;
    UINT32          m_ulServerLSR;
};

/******************************************************************************
*   RTP RTP RTP RTP RTP 
******************************************************************************/
class RTPBaseTransport: public RTSPTransport, public IHXSourceBandwidthInfo
{
public:
    RTPBaseTransport			(BOOL bIsSource);
    ~RTPBaseTransport			();
    STDMETHOD(QueryInterface)           (THIS_
                                        REFIID riid,
                                        void** ppvObj);
    STDMETHOD_(ULONG32,AddRef)      	(THIS);
    STDMETHOD_(ULONG32,Release)     	(THIS);

    /*
     *	IHXSourceBandwidthInfo methods
     */
    STDMETHOD(InitBw)			(THIS_
					IHXBandwidthManagerInput* pBwMgr);

    STDMETHOD(SetTransmitRate)		(THIS_
					UINT32 ulBitRate);
    void Done				();
    RTSPTransportTypeEnum tag		()
    {
	HX_ASSERT(!"don't call this");
	return RTSP_TR_NONE;
    };
    HX_RESULT sendPacket		(BasePacket* pPacket)
    {
	HX_ASSERT(!"don't call this");
	return HXR_UNEXPECTED;	
    }

    HX_RESULT init				();
    
    HX_RESULT reflectPacket		(BasePacket* pBasePacket, REF(IHXBuffer*)pSendBuf);
    HX_RESULT makePacket		(BasePacket* pPacket, REF(IHXBuffer*) pPacketBuf);
    void updateQoSInfo                  (UINT32 ulBytesSent);

    HX_RESULT handlePacket		(IHXBuffer* pBuffer);
    HX_RESULT handleMasterSync		(ULONG32 ulHXTime, LONG32 lHXOffsetToMaster);
    HX_RESULT anchorSync		(ULONG32 ulHXTime, ULONG32 ulNTPTime);
    virtual HX_RESULT handleRTCPSync	(NTPTime ntpTime, ULONG32 ulRTPTime);
    
    HX_RESULT streamDone		(UINT16 streamNumber);
//    IHXUDPSocket* getUDPSocket		();
    void addStreamInfo			(RTSPStreamInfo* pStreamInfo,
    					 UINT32 ulBufferDepth = TRANSPORT_BUF_DURATION_UNDEF);

    /* RTP-Info */
    HX_RESULT setFirstSeqNum		(UINT16 streamNumber, UINT16 seqNum);
    void notifyEmptyRTPInfo		(void);
    void setFirstTimeStamp		(UINT16 uStreamNumber, UINT32 ulTS,
                                         BOOL bIsRaw = FALSE);
    void setPlayRange			(UINT32 ulFrom, UINT32 ulTo);    
    HX_RESULT setFirstPlayTime		(Timeval* pTv);
    					 
    void setRTCPTransport		(RTCPBaseTransport* pRTCPTran);
    void Reset(){}
    void Restart(){}
    BOOL isRTP()			{ return TRUE; }
    BOOL isReflector()			{ return (m_ulPayloadWirePacket==1); }

    void SyncTimestamp			(IHXPacket* pPacket);

    HX_RESULT getRTCPRule (REF(UINT16) unRTCPRule);

    inline BOOL isRTCPRule (UINT16 unRuleNo)	  
    { 
	return (m_bHasRTCPRule && (unRuleNo == m_RTCPRuleNumber));
    }

    /* XXXMC
     * Special-case handling for PV clients
     */
    void setPVEmulationMode     (BOOL bEmulatePVSession);

protected:
#ifdef RTP_MESSAGE_DEBUG
    void messageFormatDebugFileOut(const char* fmt, ...);
#endif	// RTP_MESSAGE_DEBUG

    void resetStartInfoWaitQueue	(void);

    /*
     * Marker Bit Handling Routine
     */
    typedef void (RTPBaseTransport::*HandleMBitFunc)(REF(UINT8),IHXPacket*,UINT16); 
    inline void MBitRTPPktInfo (REF(UINT8)bMBit, IHXPacket* pPkt, UINT16 unRuleNo);
    inline void MBitASMRuleNo  (REF(UINT8)bMBit, IHXPacket* pPkt, UINT16 unRuleNo);


    IHXBandwidthManagerInput*		m_pBwMgrInput;
    IHXTransportSyncServer*		m_pSyncServer;
    UINT16				m_streamNumber;
    INT32				m_lRefCount;
    UINT8				m_rtpPayloadType;
    BOOL				m_bHasMarkerRule;
    UINT16				m_markerRuleNumber;
    BOOL				m_bIsSyncMaster;
    BOOL                                m_bDone;

#ifdef RTP_MESSAGE_DEBUG
    BOOL				m_bMessageDebug;
    CHXString				m_messageDebugFileName;
#endif // RTP_MESSAGE_DEBUG
       
     /*
      *	Reflection support
      */
     BOOL				m_bHasRTCPRule;
     UINT32				m_ulPayloadWirePacket;
     UINT16				m_RTCPRuleNumber;

    UINT16				m_uFirstSeqNum;
    UINT32				m_ulFirstRTPTS;
    BOOL				m_bFirstSet;
    BOOL				m_bWeakStartSync;

    INT32				m_lTimeOffsetHX;
    INT32				m_lTimeOffsetRTP;
    INT32				m_lOffsetToMasterHX;
    INT32				m_lOffsetToMasterRTP;
    INT32				m_lSyncOffsetHX;
    INT32				m_lSyncOffsetRTP;
    INT32				m_lNTPtoHXOffset;
    BOOL				m_bNTPtoHXOffsetSet;

    ULONG32				m_ulLastRTPTS;
    ULONG32				m_ulLastHXTS;
    ULONG32				m_ulLastRawRTPTS;
    BOOL				m_bLastTSSet;

    CHXSimpleList			m_StartInfoWaitQueue;
    BOOL				m_bWaitForStartInfo;
    BOOL				m_bAbortWaitForStartInfo;
    ULONG32				m_ulStartInfoWaitStartTime;

    UINT32                              m_ulAvgPktSz;

    /*
     * RTP-Info:  According to RFC2326, it is possible not to have one of them,
     * so if it is missing, take care of it right here in transport 
     */
    BOOL				m_bSeqNoSet;
    /* m_bRTPTimeSet is used differently on the server and the client */
    BOOL    				m_bRTPTimeSet;


    Timeval*				m_pFirstPlayTime;
    

    /* this class does everything for RTCP */
    ReportHandler*			m_pReportHandler;

    RTCPBaseTransport*			m_pRTCPTran;

    BOOL				m_bIsLive;
    UINT32				m_ulExtensionSupport;

    /*
     *	This stream may not have been SETUPed. 
     */
    BOOL				m_bActive;

    /* XXXMC
     * Support for PV Emulation
     */
    BOOL                m_bEmulatePVSession;

    /*
     * Markerbit Handling
     */
    HandleMBitFunc	m_pMBitHandler;

    /*
     * Reflector RTP-Info 
     */
    struct ReflectorInfo
    {
	ReflectorInfo()
	    : m_unSeqNoOffset(0)
	    , m_ulRTPTSOffset(0)
	{}	    
	UINT16		m_unSeqNoOffset;
	UINT32		m_ulRTPTSOffset;
    }			m_reflectorInfo;

    UINT8           m_cLSRRead;
    UINT8           m_cLSRWrite;
    LSRRecord       m_LSRHistory [LSR_HIST_SZ];
    UINT32          MapLSR(UINT32 ulSourceLSR);

    IHXQoSTransportAdaptationInfo*      m_pQoSInfo;

    friend class RTCPBaseTransport;
    friend class RTCPUDPTransport;
    friend class RTCPTCPTransport;

private:
    HX_RESULT _handlePacket(IHXBuffer* pBuffer, BOOL bIsRealTime);
};

/*
*   NOTE:
*   Each RTP transport represents a RTP session because transport is bounded to a pair
*   of addr and ports.

*   As it is currently implemented, RTP transport can NOT have more than one stream.

*   Currently, we do NOT support RTSP/RTP multicast.  so we don't need to do a number
*   of things that should be done if we were to support multicast.
*   1. Maintain a table of members (instread we have just one member)
*   2. Don't really need to calculate RTCP intervals (instead every 5 sec)

*   There are two assumptions due to the nature of 1 to 1 or 1 to many session
*   1. A server (server) never receives RTP.
*   2. There is only one sender (server) in a session.
*/

class RTPUDPTransport: public RTPBaseTransport
{
public:
    RTPUDPTransport			(BOOL bIsSource);
    ~RTPUDPTransport			();
    void Done				();
    RTSPTransportTypeEnum tag		();
    HX_RESULT init			(IUnknown* pContext,
					IHXUDPSocket* pSocket,
					IHXRTSPTransportResponse* pResp);
    void setForeignAddress		(UINT32 foreignAddr,
    					UINT16 foreignPort);
    HX_RESULT sendPacket		(BasePacket* pPacket);

    IHXUDPSocket* getUDPSocket		();
//    void setRTCPTransport		(RTCPUDPTransport* pRTCPTran);

    /* XXXMC
     * Special-case handling for PV clients
     */
    HX_RESULT sendPVHandshakeResponse(UINT8* pPktPayload);

    HX_RESULT handlePacket(IHXBuffer* pBuffer);

    void            JoinMulticast(UINT32 ulAddress, UINT32 ulPort, IHXUDPSocket* pUDP);
    IHXUDPSocket*   getMulticastSocket(void);

protected:
    class KeepAliveCB : public IHXCallback
    {
    public:
	KeepAliveCB(RTPUDPTransport* pTransport);

        /*
         *      IUnknown methods
         */
        STDMETHOD(QueryInterface)       (THIS_
                                        REFIID riid,
                                        void** ppvObj);

        STDMETHOD_(ULONG32,AddRef)      (THIS);

        STDMETHOD_(ULONG32,Release)     (THIS);

        /*
         *      IHXCallback methods
         */
        STDMETHOD(Func)                 (THIS);

    private:
	RTPUDPTransport*		m_pTransport;
        LONG32              		m_lRefCount;
        ~KeepAliveCB();
        PRIVATE_DESTRUCTORS_ARE_NOT_A_CRIME
    };
    friend class KeepAliveCB;

    HX_RESULT onNATKeepAlive();

private:
    HX_RESULT writePacket		(IHXBuffer* pSendBuffer);

    IHXUDPSocket*              	m_pUDPSocket;
    UINT32                      	m_foreignAddr;
    UINT16                      	m_foreignPort;
//    RTCPUDPTransport*			m_pRTCPTran;       

    CHXKeepAlive m_keepAlive;
    UINT16       m_keepAliveSeq;  // Sequence # for keepalive packets

    UINT32	    m_ulCurrentMulticastAddress;
    UINT32	    m_ulCurrentMulticastPort;
    IHXUDPSocket*   m_pMCastUDPSocket;

    friend class RTCPBaseTransport;
    friend class RTCPUDPTransport;
};

inline IHXUDPSocket*
RTPUDPTransport::getUDPSocket()
{
    return m_pUDPSocket;
}

inline IHXUDPSocket*
RTPUDPTransport::getMulticastSocket()
{
    return m_pMCastUDPSocket;
}

class RTPTCPTransport: public RTPBaseTransport
{
public:
    RTPTCPTransport			(BOOL bIsSource);
    ~RTPTCPTransport    		();
    void Done				();
    
    RTSPTransportTypeEnum tag		();
    HX_RESULT init			(IUnknown* pContext,
			 		IHXTCPSocket* pSocket,
			 		IHXRTSPTransportResponse* pResp);
    void setInterleaveChannel		(INT8 tcpInterleave)
    {	
	m_tcpInterleave = tcpInterleave;
    }
    HX_RESULT sendPacket		(BasePacket* pPacket);

//    HX_RESULT streamDone		(UINT16 streamNumber);    

//    void setRTCPTransport		(RTCPTCPTransport* pRTCPTran);
 protected:
    IHXTCPSocket* 			m_pTCPSocket;
    
private:
    HX_RESULT writePacket         	(IHXBuffer* pBuf);

    INT8				m_tcpInterleave;

    friend class RTCPBaseTransport;
    friend class RTCPTCPTransport;
};


/******************************************************************************
*   RTCP RTCP RTCP RTCP RTCP
******************************************************************************/
class RTCPBaseTransport: public RTSPTransport,
			 public IHXQoSSignalSourceResponse
{
public:
    RTCPBaseTransport			(BOOL bIsSender);
    ~RTCPBaseTransport			();
    STDMETHOD(QueryInterface)           (THIS_
                                        REFIID riid,
                                        void** ppvObj);
    STDMETHOD_(ULONG32,AddRef)		(THIS);
    STDMETHOD_(ULONG32,Release)		(THIS);
    void Done				();

    RTSPTransportTypeEnum tag		()
    {
	HX_ASSERT(!"don't call this");
	return RTSP_TR_NONE;
    }
    HX_RESULT sendPacket		(BasePacket* pPacket)
    {
	HX_ASSERT(!"don't call this");
	return HXR_UNEXPECTED;
    }
    HX_RESULT handlePacket		(IHXBuffer* pBuffer);
    HX_RESULT streamDone		(UINT16 streamNumber)
    {
	HX_ASSERT(!"don't call this");
	return HXR_UNEXPECTED;
    }

    void addStreamInfo(RTSPStreamInfo* pStreamInfo,
		       UINT32 ulBufferDepth = TRANSPORT_BUF_DURATION_UNDEF);

    HX_RESULT init				();
    void setSessionID		        (const char* pSessionID);

    void Reset(){}
    void Restart(){}

    HX_RESULT SetTSConverter(CHXTimestampConverter::ConversionFactors conversionFactors);

    CHXTimestampConverter* GetTSConverter(void)    { return m_pTSConverter; }

    class ReportCallback : public IHXCallback
    {
    public:
	ReportCallback			(RTCPBaseTransport* pTransport);

        /*
         *      IUnknown methods
         */
        STDMETHOD(QueryInterface)       (THIS_
                                        REFIID riid,
                                        void** ppvObj);

        STDMETHOD_(ULONG32,AddRef)      (THIS);

        STDMETHOD_(ULONG32,Release)     (THIS);

        /*
         *      IHXCallback methods
         */
        STDMETHOD(Func)                 (THIS);

    private:
	RTCPBaseTransport*		m_pTransport;
        LONG32              		m_lReportRefCount;
        ~ReportCallback			();
        PRIVATE_DESTRUCTORS_ARE_NOT_A_CRIME
    };
    friend class ReportCallback;

    virtual HX_RESULT reflectRTCP		(IHXBuffer* pSendBuf) = 0;
    virtual HX_RESULT sendSenderReport		() = 0;
    virtual HX_RESULT sendReceiverReport	() = 0;
    virtual HX_RESULT sendBye			() = 0;

    // IHXQoSSignalSourceResponse
    STDMETHOD (SignalBusReady)(THIS_ HX_RESULT hResult, IHXQoSSignalBus* pBus, 
			       IHXBuffer* pSessionId);

protected:
    /* caller is responsible for freeing pSendBuf */
    HX_RESULT makeSenderReport		(REF(IHXBuffer*) pSendBuf);
    HX_RESULT makeReceiverReport	(REF(IHXBuffer*) pSendBuf);
    HX_RESULT makeBye			(REF(IHXBuffer*) pSendBuf);

    HX_RESULT startScheduler		();
    HX_RESULT stopScheduler		();
    BOOL      isShedulerStarted		(void)	{ return m_bSchedulerStarted; }
    void      scheduleNextReport	();
    
    RTPBaseTransport*			m_pDataTransport;
    // XXXGo
    // make sure stream number that RTCP is using is the same as the one
    // in RTP
    UINT16				m_streamNumber;
    INT32				m_lRefCount;
    BOOL				m_bSendBye;

    BOOL				m_bSendReport;
    ReportCallback*			m_pReportCallback;
    BOOL				m_bCallbackPending;
    CallbackHandle			m_reportTimeoutID;
    BOOL				m_bSchedulerStarted;
    BOOL                                m_bSendRTCP;

    // a random number for CNAME...
    BYTE*				m_pcCNAME;

    /* this class does everything for RTCP */
    /* and pointing to the same instance that RTPBaseTransport has */
    ReportHandler*			m_pReportHandler;

    CHXTimestampConverter*		m_pTSConverter;

    IHXThreadSafeScheduler*             m_pTSScheduler;

    /* For placing recevier reports on QoS Signal Bus */
    IHXQoSSignalBus*                    m_pSignalBus;
    IHXQoSSignal*                       m_pQoSSignal_RR;
    IHXQoSSignal*                       m_pQoSSignal_APP;
    IHXBuffer*                          m_pSessionId;

    /* Timing of RTCP RR Interval: */
    UINT32                              m_ulLastRR;
    UINT32                              m_ulLastSeq;
    UINT32                              m_ulLastLoss;
    UINT32                              m_ulLastRate;
    UINT32                              m_ulRRIntvl;

    friend class RTPBaseTransport;
    friend class RTPUDPTransport;
    friend class RTPTCPTransport;
};

class RTCPUDPTransport: public RTCPBaseTransport
{
public:
    RTCPUDPTransport			(BOOL bIsSender);
    ~RTCPUDPTransport			();
    void Done				();

    HX_RESULT init			(IUnknown* pContext,
    					IHXUDPSocket* pSocket,
					RTPUDPTransport* pDataTransport,
					IHXRTSPTransportResponse* pResp,					
					UINT16 streamNumber);
    RTSPTransportTypeEnum tag		();
    HX_RESULT streamDone		(UINT16 streamNumber);
    void setForeignAddress		(UINT32 foreignAddr,
    					UINT16 foreignPort);
    IHXUDPSocket* getUDPSocket	();

    HX_RESULT handlePacket(IHXBuffer* pBuffer);

    void            JoinMulticast(UINT32 ulAddress, UINT32 ulPort, IHXUDPSocket* pUDP);
    IHXUDPSocket*   getMulticastSocket(void);

protected:
    class KeepAliveCB : public IHXCallback
    {
    public:
	KeepAliveCB(RTCPUDPTransport* pTransport);

        /*
         *      IUnknown methods
         */
        STDMETHOD(QueryInterface)       (THIS_
                                        REFIID riid,
                                        void** ppvObj);

        STDMETHOD_(ULONG32,AddRef)      (THIS);

        STDMETHOD_(ULONG32,Release)     (THIS);

        /*
         *      IHXCallback methods
         */
        STDMETHOD(Func)                 (THIS);

    private:
	RTCPUDPTransport*		m_pTransport;
        LONG32              		m_lRefCount;
        ~KeepAliveCB();
        PRIVATE_DESTRUCTORS_ARE_NOT_A_CRIME
    };
    friend class KeepAliveCB;

    HX_RESULT onNATKeepAlive();

private:
    HX_RESULT reflectRTCP		(IHXBuffer* pSendBuf);
    HX_RESULT sendSenderReport		();
    HX_RESULT sendReceiverReport	();
    HX_RESULT sendBye			();

    
    IHXUDPSocket*   m_pUDPSocket;
    UINT32          m_foreignAddr;
    UINT16          m_foreignPort;

    CHXKeepAlive    m_keepAlive;

    UINT32	    m_ulCurrentMulticastAddress;
    UINT32	    m_ulCurrentMulticastPort;
    IHXUDPSocket*   m_pMCastUDPSocket;

    friend class RTPBaseTransport;
    friend class RTPUDPTransport;
};

inline IHXUDPSocket*
RTCPUDPTransport::getUDPSocket()
{
    return m_pUDPSocket;
}

inline IHXUDPSocket*
RTCPUDPTransport::getMulticastSocket()
{
    return m_pMCastUDPSocket;
}

class RTCPTCPTransport: public RTCPBaseTransport
{
public:
    RTCPTCPTransport			(BOOL bIsSender);
    ~RTCPTCPTransport			();
    void Done				();

    HX_RESULT init			(IUnknown* pContext,
    					IHXTCPSocket* pSocket,
					RTPTCPTransport* pDataTransport,
					IHXRTSPTransportResponse* pResp,
					UINT16 streamNumber);
    void setInterleaveChannel		(INT8 tcpInterleave)
    {
	m_tcpInterleave = tcpInterleave;
    }
    RTSPTransportTypeEnum tag		();
    HX_RESULT streamDone		(UINT16 streamNumber);

private:
    HX_RESULT reflectRTCP		(IHXBuffer* pSendBuf);
    HX_RESULT sendSenderReport		();
    HX_RESULT sendReceiverReport	();
    HX_RESULT sendBye			();
    HX_RESULT writePacket		(IHXBuffer* pBuf);
    
    IHXTCPSocket*			m_pTCPSocket;
    INT8				m_tcpInterleave;
//    friend class RTPBaseTransport;
//    friend class RTPTCPTransport;
};

#endif /* ndef _RTPTRAN_H_ */