292 lines
7.3 KiB
C++
292 lines
7.3 KiB
C++
// RTPSession.h : Declaration of the CRTPSession
|
||
|
||
#ifndef __RTPSESSION_H_
|
||
#define __RTPSESSION_H_
|
||
|
||
#include "resource.h" // main symbols
|
||
#include "queue.h"
|
||
|
||
#ifndef MAX_MISORDER
|
||
const int MAX_MISORDER =20;
|
||
#endif
|
||
const int MAX_DROPPED =30;
|
||
|
||
typedef short PORT;
|
||
|
||
|
||
|
||
|
||
typedef unsigned __int64 NTP_TS;
|
||
|
||
|
||
//typedef void (* PRTPRECVCALLBACK)(DWORD dwStatus, DWORD_PTR dwCallback, NETBUF *pNetBuf, DWORD ssrc, DWORD ts, UINT seq, BOOL fMark);
|
||
|
||
typedef struct {
|
||
UINT sessionId;
|
||
UINT mediaId;
|
||
BOOL fSend;
|
||
PSOCKADDR_IN pLocalAddr;
|
||
PSOCKADDR_IN pLocalRTCPAddr;
|
||
PSOCKADDR_IN pRemoteAddr;
|
||
PSOCKADDR_IN pRemoteRTCPAddr;
|
||
} RTPCHANNELDESC;
|
||
|
||
typedef struct {
|
||
RTP_HDR_T hdr; // header template for quick formatting
|
||
RTP_STATS sendStats; // statistics
|
||
} RTP_SEND_STATE;
|
||
|
||
typedef struct {
|
||
RTP_STATS rcvStats; // statistics
|
||
NTP_TS ntpTime;
|
||
DWORD rtpTime;
|
||
|
||
} RTP_RECV_STATE;
|
||
|
||
|
||
// generic UDP socket wrapper
|
||
// defined in its entirety here
|
||
class UDPSOCKET {
|
||
SOCKET Sock;
|
||
SOCKADDR_IN local_sin;
|
||
SOCKADDR_IN remote_sin;
|
||
int local_sin_len;
|
||
int remote_sin_len;
|
||
|
||
public:
|
||
UDPSOCKET() {
|
||
ZeroMemory(&local_sin,sizeof(local_sin));
|
||
ZeroMemory(&remote_sin,sizeof(remote_sin));
|
||
Sock = INVALID_SOCKET;}
|
||
~UDPSOCKET()
|
||
{
|
||
Cleanup();
|
||
}
|
||
|
||
VOID SetRemoteAddr(PSOCKADDR_IN psin) {remote_sin = *psin;};
|
||
VOID SetLocalAddress(PSOCKADDR_IN psin) {local_sin = *psin;};
|
||
PSOCKADDR_IN GetLocalAddress() {return &local_sin;};
|
||
PSOCKADDR_IN GetRemoteAddress() {return &remote_sin;};
|
||
VOID SetRemotePort(PORT port) {remote_sin.sin_port = htons(port);};
|
||
VOID SetLocalPort(PORT port) {local_sin.sin_port = htons(port);};
|
||
PORT GetRemotePort() {return (ntohs(remote_sin.sin_port));};
|
||
PORT GetLocalPort() {return(ntohs(local_sin.sin_port));};
|
||
SOCKET GetSock() {return Sock;};
|
||
BOOL NewSock()
|
||
{
|
||
if(Sock == INVALID_SOCKET)
|
||
{
|
||
|
||
Sock = (*RRCMws.WSASocket) (AF_INET,
|
||
SOCK_DGRAM,
|
||
WS2Enabled ? FROM_PROTOCOL_INFO : 0,
|
||
&RRCMws.RTPProtInfo,
|
||
0,
|
||
WSA_FLAG_OVERLAPPED);
|
||
}
|
||
return(Sock != INVALID_SOCKET);
|
||
}
|
||
|
||
VOID Cleanup()
|
||
{
|
||
if(Sock != INVALID_SOCKET)
|
||
{
|
||
(*RRCMws.closesocket)(Sock);
|
||
Sock = INVALID_SOCKET;
|
||
}
|
||
|
||
}
|
||
int BindMe()
|
||
{
|
||
return (*RRCMws.bind)(Sock, (LPSOCKADDR)&local_sin, sizeof (local_sin));
|
||
}
|
||
|
||
};
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// CRTPPacket (internal object representing a received RTPPacket)
|
||
class CRTPPacket1
|
||
{
|
||
public:
|
||
CRTPPacket1()
|
||
{
|
||
m_wsabuf.buf = NULL;
|
||
m_wsabuf.len = 0;
|
||
m_cbSize = 0;
|
||
|
||
}
|
||
~CRTPPacket1();
|
||
|
||
public:
|
||
|
||
HRESULT Init(UINT cbMaxSize); // allocates buffer of size cbMaxSize
|
||
|
||
WSAOVERLAPPED *GetOverlapped() {return &m_overlapped;}
|
||
void SetActual(UINT len) {m_wsabuf.len = len;}
|
||
void RestoreSize() {m_wsabuf.len = m_cbSize;}
|
||
static CRTPPacket1 *GetRTPPacketFromOverlapped(WSAOVERLAPPED *pOverlapped)
|
||
{
|
||
return ( (CRTPPacket1 *)((char *)pOverlapped - (UINT_PTR)(&((CRTPPacket1 *)0)->m_overlapped)));
|
||
}
|
||
static CRTPPacket1 *GetRTPPacketFromWSABUF(WSABUF *pBuf)
|
||
{
|
||
return ( (CRTPPacket1 *)((char *)pBuf - (UINT_PTR)(&((CRTPPacket1 *)0)->m_wsabuf)));
|
||
}
|
||
WSABUF *GetWSABUF() {return &m_wsabuf;}
|
||
DWORD GetTimestamp() {return (((RTP_HDR_T *)m_wsabuf.buf)->ts);}
|
||
void SetTimestamp(DWORD timestamp) {((RTP_HDR_T *)m_wsabuf.buf)->ts = timestamp;}
|
||
UINT GetSeq() {return (((RTP_HDR_T *)m_wsabuf.buf)->seq);}
|
||
void SetSeq(UINT seq) {((RTP_HDR_T *)m_wsabuf.buf)->seq = (WORD)seq;}
|
||
BOOL GetMarkBit() {return (((RTP_HDR_T *)m_wsabuf.buf)->m);}
|
||
private:
|
||
WSAOVERLAPPED m_overlapped;
|
||
WSABUF m_wsabuf;
|
||
UINT m_cbSize; // (max) size of packet
|
||
};
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// CRTPSession
|
||
class ATL_NO_VTABLE CRTPSession :
|
||
public CComObjectRootEx<CComMultiThreadModel>,
|
||
// public CComCoClass<CRTPSession, &CLSID_RTPSession>,
|
||
public IRTPSend,
|
||
public IRTPSession,
|
||
public IRTPRecv
|
||
{
|
||
public:
|
||
CRTPSession();
|
||
HRESULT FinalRelease();
|
||
|
||
|
||
|
||
//DECLARE_REGISTRY_RESOURCEID(IDR_RTPSESSION)
|
||
|
||
BEGIN_COM_MAP(CRTPSession)
|
||
COM_INTERFACE_ENTRY(IRTPSend)
|
||
COM_INTERFACE_ENTRY(IRTPSession)
|
||
COM_INTERFACE_ENTRY(IRTPRecv)
|
||
END_COM_MAP()
|
||
|
||
// IRTPSend
|
||
public:
|
||
STDMETHOD(Send)(
|
||
WSABUF *pWsabufs,
|
||
UINT nWsabufs,
|
||
WSAOVERLAPPED *pOverlapped,
|
||
LPWSAOVERLAPPED_COMPLETION_ROUTINE pWSAPC );
|
||
STDMETHOD(GetSendStats)(RTP_STATS *pSendStats) {
|
||
*pSendStats = m_ss.sendStats;return S_OK;
|
||
}
|
||
|
||
// IRTPRecv
|
||
STDMETHOD(SetRecvNotification) (PRTPRECVCALLBACK , DWORD_PTR dwCallback, UINT nBufs);
|
||
STDMETHOD(CancelRecvNotification) ();
|
||
// called by CRTPMediaStream to free accumulated packets
|
||
STDMETHOD (FreePacket)(WSABUF *pBuf) ;
|
||
STDMETHOD(GetRecvStats)(RTP_STATS *pSendStats) {
|
||
*pSendStats = m_rs.rcvStats;return S_OK;
|
||
}
|
||
|
||
|
||
// IRTPSession
|
||
STDMETHOD(SetLocalAddress)(BYTE *sockaddr, UINT cbAddr);
|
||
STDMETHOD(SetRemoteRTPAddress)(BYTE *sockaddr, UINT cbAddr);
|
||
STDMETHOD(SetRemoteRTCPAddress)(BYTE *sockaddr, UINT cbAddr);
|
||
STDMETHOD(GetLocalAddress)(const BYTE **sockaddr, UINT *pcbAddr);
|
||
STDMETHOD(GetRemoteRTPAddress)(const BYTE **sockaddr, UINT *pcbAddr);
|
||
STDMETHOD(GetRemoteRTCPAddress)(const BYTE **sockaddr, UINT *pcbAddr);
|
||
STDMETHOD(CreateRecvRTPStream)(DWORD ssrc, IRTPRecv **ppIRTPRecv);
|
||
STDMETHOD(SetSendFlowspec)(FLOWSPEC *pSendFlowspec);
|
||
STDMETHOD(SetRecvFlowspec)(FLOWSPEC *pRecvFlowspec);
|
||
STDMETHOD (SetMaxPacketSize) (UINT cbPacketSize);
|
||
|
||
// other non-COM methods
|
||
// called by CRTPMediaStream to request that receive buffers be posted
|
||
HRESULT PostRecv();
|
||
|
||
private:
|
||
|
||
UDPSOCKET *m_rtpsock;
|
||
UDPSOCKET *m_rtcpsock;
|
||
UINT m_sessionId;
|
||
UINT m_mediaId;
|
||
class CRTPSession *m_pSessNext;
|
||
static class CRTPSession *m_pSessFirst;
|
||
|
||
HANDLE m_hRTPSession;
|
||
QOS m_Qos;
|
||
|
||
UINT m_clockRate;
|
||
|
||
// receive stuff
|
||
UINT m_uMaxPacketSize;
|
||
QueueOf<CRTPPacket1 *> m_FreePkts;
|
||
UINT m_nBufsPosted;
|
||
// this should be per remote SSRC
|
||
PRTPRECVCALLBACK m_pRTPCallback;
|
||
DWORD_PTR m_dwCallback;
|
||
RTP_RECV_STATE m_rs;
|
||
|
||
// used by RTPRecvFrom()
|
||
int m_rcvSockAddrLen;
|
||
SOCKADDR m_rcvSockAddr;
|
||
|
||
// send stuff
|
||
DWORD m_numBytesSend;
|
||
int m_lastSendError;
|
||
WSAOVERLAPPED m_sOverlapped; // used only for synchronous Send()
|
||
BOOL m_fSendingSync; // TRUE if m_sOverlapped is in use
|
||
RTP_SEND_STATE m_ss;
|
||
|
||
HRESULT Initialize(UINT sessionId, UINT mediaId,BYTE *sockaddr, UINT cbAddr);
|
||
BOOL SelectPorts();
|
||
HRESULT SetMulticastAddress(PSOCKADDR_IN );
|
||
|
||
friend void RRCMNotification(int ,DWORD_PTR,DWORD_PTR,DWORD_PTR);
|
||
friend void CALLBACK WS2SendCB (DWORD , DWORD, LPWSAOVERLAPPED, DWORD );
|
||
friend void CALLBACK WS2RecvCB (DWORD , DWORD, LPWSAOVERLAPPED, DWORD );
|
||
friend class CRTP;
|
||
|
||
|
||
void RTCPNotify(int,DWORD_PTR dwSSRC,DWORD_PTR rtcpsock);
|
||
|
||
BOOL GetRTCPReport();
|
||
|
||
};
|
||
|
||
typedef CComObject<CRTPSession> ObjRTPSession; // instantiable class
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// CRTP - top level RTP interface
|
||
//
|
||
class ATL_NO_VTABLE CRTP:
|
||
public CComObjectRootEx<CComMultiThreadModel>,
|
||
public CComCoClass<CRTP, &CLSID_RTP>,
|
||
public IRTP
|
||
{
|
||
public:
|
||
|
||
DECLARE_REGISTRY_RESOURCEID(IDR_RTP)
|
||
|
||
BEGIN_COM_MAP(CRTP)
|
||
COM_INTERFACE_ENTRY(IRTP)
|
||
END_COM_MAP()
|
||
|
||
// IRTP
|
||
public:
|
||
STDMETHOD(OpenSession)(
|
||
UINT sessionId, // client specified unique identifier for the session
|
||
DWORD flags, // SESSION_SEND, SESSION_RECV, SESSION_MULTICAST
|
||
BYTE *localAddr, // Local socket interface addr to bind to
|
||
UINT cbAddr, // sizeof(SOCKADDR)
|
||
IRTPSession **ppIRTP); // [output] pointer to RTPSession
|
||
|
||
// STDMETHOD(CreateSink)( IRTPSink **ppIRTPSink);
|
||
private:
|
||
static BOOL m_WSInitialized;
|
||
};
|
||
|
||
#endif //__RTPSINK_H_
|
||
|