📄 rtp.c
字号:
/***********************************************************************
Copyright (c) 2002 RADVISION Ltd.
************************************************************************
NOTICE:
This document contains information that is confidential and proprietary
to RADVISION Ltd.. No part of this document may be reproduced in any
form whatsoever without written prior approval by RADVISION Ltd..
RADVISION Ltd. reserve the right to revise this publication and make
changes without obligation to notify any person of such revisions or
changes.
***********************************************************************/
#include "rvstdio.h"
#include "rvmemory.h"
#include "rvtimestamp.h"
#include "rvrandomgenerator.h"
#include "rvhost.h"
#include "rvsocket.h"
#include "rvselect.h"
#include "rvcbase.h"
#include "bitfield.h"
#include "rtputil.h"
#include "rvrtp.h"
#include "rvrtcp.h"
#ifdef __cplusplus
extern "C" {
#endif
#define BUILD_VER_NUM(_max, _min, _dot1, _dot2) \
((RvUint32)((_max << 24) + (_min << 16) + (_dot1 << 8) + _dot2))
#define VERSION_STR "4.1.0.0"
#define VERSION_NUM BUILD_VER_NUM(4, 1, 0, 0)
#define RV_RTP_MAXIPS RvUint32Const(20)
/* Internal RTP instance used. There a single such object */
typedef struct
{
RvSelectEngine* selectEngine; /* Select engine used */
RvUint32 localIp; /* IP to bind to */
RvUint32 hostIPs[RV_RTP_MAXIPS]; /* Local host IPs */
RvUint32 timesInitialized; /* Times the RTP was initialized */
RvRandomGenerator randomGenerator; /* Random numbers generator to use */
} RvRtpInstance;
/* RTP instance to use */
static RvRtpInstance rvRtpInstance;
#if 1
typedef struct
{
RvBool isAllocated; /* RV_TRUE if the RTP package allocated this struct internally */
RvSocket socket; /* UDP socket used for this session */
RvSelectFd selectFd; /* fd object to use for non-blocking mode */
RvUint32 sSrc;
RvUint32 sSrcMask;
RvUint32 sSrcPattern;
LPRTPEVENTHANDLER eventHandler;
void * context;
RvUint16 sequenceNumber;
RvAddress remoteAddress; /* Remote address of this session */
RvBool remoteAddressSet; /* RV_TRUE if we already set the remote address */
RvBool useSequenceNumber;
HRTCPSESSION hRTCP; /* Associate RTCP session if available */
} rtpSession; /* HRTPSESSION */
#endif
/* local functions */
static RvBool isMyIP(RvUint32 ip);
static void rtpEvent(
IN RvSelectEngine* selectEngine,
IN RvSelectFd* fd,
IN RvSelectEvents selectEvent,
IN RvBool error);
/* == Basic RTP Functions == */
RVAPI
RvInt32 RVCALLCONV rtpInit(void)
{
RvStatus status;
status = RvCBaseInit();
if (status != RV_OK)
return status;
if (rvRtpInstance.timesInitialized == 0)
{
RvAddress addresses[RV_RTP_MAXIPS];
RvUint32 numAddrs = RV_RTP_MAXIPS;
RvUint32 i;
/* Find the list of host addresses we have */
status = RvHostLocalGetAddress(&numAddrs, addresses);
if (status != RV_OK)
{
RvCBaseEnd();
return status;
}
for (i = 0; i < numAddrs; i++)
rvRtpInstance.hostIPs[i] = RvAddressIpv4GetIp(RvAddressGetIpv4(addresses + i));
while (i > 0)
{
i--;
RvAddressDestruct(addresses+i);
}
if (status != RV_OK)
{
RvCBaseEnd();
return status;
}
/* Create a random generator */
RvRandomGeneratorConstruct(&rvRtpInstance.randomGenerator,
(RvRandom)(RvTimestampGet()>>8));
}
status = RvRtpInitSelectEngine(&rvRtpInstance.selectEngine);
if (status != RV_OK)
{
RvCBaseEnd();
return status;
}
rvRtpInstance.timesInitialized++;
return RV_OK;
}
RVAPI
RvInt32 RVCALLCONV rtpInitEx(RvUint32 ip)
{
RvInt32 rc;
if ((rc=rtpInit()) != RV_ERROR_UNKNOWN)
rvRtpInstance.localIp = ip;
return rc;
}
/************************************************************************************
* rtpSetLocalAddress
* description: Set the local address to use for calls to rtpOpenXXX functions.
* This parameter overrides the value given in rtpInitEx() for all
* subsequent calls.
* input: ip - Local IP address to use
* output: none.
* return value: Non-negative value on success
* Negative value on failure
***********************************************************************************/
RVAPI
int RVCALLCONV rtpSetLocalAddress(IN RvUint32 ip)
{
rvRtpInstance.localIp = ip;
return RV_OK;
}
RVAPI
void RVCALLCONV rtpEnd(void)
{
rvRtpInstance.timesInitialized--;
if (rvRtpInstance.timesInitialized == 0)
{
RvRandomGeneratorDestruct(&rvRtpInstance.randomGenerator);
}
RvRtpEndSelectEngine();
RvCBaseEnd();
}
RVAPI
int RVCALLCONV rtpGetAllocationSize(void)
{
return sizeof(rtpSession);
}
/************************************************************************************
* rtpOpenFrom
* description: Opens an RTP session in the memory that the application allocated.
* input: port - The UDP port number to be used for the RTP session.
* ssrcPattern - Synchronization source Pattern value for the RTP session.
* ssrcMask - Synchronization source Mask value for the RTP session.
* buffer - Application allocated buffer with a value no less than the
* value returned by the function rtpGetAllocationSize().
* bufferSize - size of the buffer.
* output: none.
* return value: If no error occurs, the function returns the handle for the opened RTP
* session. Otherwise, it returns NULL.
***********************************************************************************/
RVAPI
HRTPSESSION RVCALLCONV rtpOpenFrom(
IN RvUint16 port,
IN RvUint32 ssrcPattern,
IN RvUint32 ssrcMask,
IN void* buffer,
IN int bufferSize)
{
rtpSession *s = (rtpSession *)buffer;
RvAddress localAddress;
RvRandom randomValue;
RvStatus res;
if (bufferSize < rtpGetAllocationSize())
return NULL;
memset(buffer, 0 , (RvSize_t)rtpGetAllocationSize());
/* Get a random value for the beginning sequence number */
RvRandomGeneratorGetValue(&rvRtpInstance.randomGenerator, &randomValue);
s->isAllocated = RV_FALSE;
s->sSrcPattern = ssrcPattern;
s->sSrcMask = ssrcMask;
s->sequenceNumber = (RvUint16)randomValue;
RvAddressConstructIpv4(&localAddress, rvRtpInstance.localIp, port);
/* Open and bind the socket */
res = RvSocketConstruct(&s->socket, RV_ADDRESS_TYPE_IPV4, RvSocketProtocolUdp);
if (res == RV_OK)
{
res = RvSocketSetBuffers(&s->socket, 8192, 8192);
if (res == RV_OK)
res = RvSocketSetBroadcast(&s->socket, RV_TRUE);
if (res == RV_OK)
res = RvSocketSetBlocking(&s->socket, RV_TRUE);
if (res == RV_OK)
res = RvSocketBind(&s->socket, &localAddress, NULL);
if (res != RV_OK)
RvSocketDestruct(&s->socket, RV_FALSE, NULL);
}
RvAddressDestruct(&localAddress);
if (res == RV_OK)
{
rtpRegenSSRC((HRTPSESSION)s);
return (HRTPSESSION)s;
}
else
{
return (HRTPSESSION)NULL;
}
}
/************************************************************************************
* rtpOpen
* description: Opens an RTP session. The RTP Stack allocates an object and the
* memory needed for the RTP session. It also opens a socket and waits
* for packets. rtpOpen() also returns the handle of this session to
* the application.
* input: port - The UDP port number to be used for the RTP session.
* ssrcPattern - Synchronization source Pattern value for the RTP session.
* ssrcMask - Synchronization source Mask value for the RTP session.
* output: none.
* return value: If no error occurs, the function returns the handle for the opened RTP
* session. Otherwise, it returns NULL.
***********************************************************************************/
RVAPI
HRTPSESSION RVCALLCONV rtpOpen(
IN RvUint16 port,
IN RvUint32 ssrcPattern,
IN RvUint32 ssrcMask)
{
return rtpOpenEx(port, ssrcPattern, ssrcMask, NULL);
}
/************************************************************************************
* rtpOpenEx
* description: Opens an RTP session and an associated RTCP session.
* input: port - The UDP port number to be used for the RTP session.
* ssrcPattern - Synchronization source Pattern value for the RTP session.
* ssrcMask - Synchronization source Mask value for the RTP session.
* cname - The unique name representing the source of the RTP data.
* output: none.
* return value: If no error occurs, the function returns the handle for the open
* RTP session. Otherwise, the function returns NULL.
***********************************************************************************/
RVAPI
HRTPSESSION RVCALLCONV rtpOpenEx(
IN RvUint16 port,
IN RvUint32 ssrcPattern,
IN RvUint32 ssrcMask,
IN char * cname)
{
/* allocate rtp session.*/
rtpSession* s;
RvStatus res;
res = RvMemoryAlloc(NULL, (void**)&s, (RvSize_t)rtpGetAllocationSize());
if (res != RV_OK)
return NULL;
if ((rtpSession *)rtpOpenFrom(port, ssrcPattern, ssrcMask, (void*)s, rtpGetAllocationSize())==NULL)
{
RvMemoryFree(s);
return NULL;
}
s->isAllocated=RV_TRUE;
if (cname)
{
/* Open a new rtcp session.The port for an RTCP session is always
(RTP port + 1).*/
s->hRTCP = rtcpOpen(s->sSrc, (RvUint16)((port)?port+1:port), cname);
if (s->hRTCP == NULL)
{
/* Bad RTCP - let's just kill the RTP and be done with it */
rtpClose((HRTPSESSION)s);
s = NULL;
}
}
return (HRTPSESSION)s;
}
/************************************************************************************
* rtpClose
* description: Close RTP session.
* input: hRTP - Handle of the RTP session.
* output: none.
* return value: If an error occurs, the function returns a negative value.
* If no error occurs, the function returns a non-negative value.
***********************************************************************************/
RVAPI
RvUint32 RVCALLCONV rtpClose(
IN HRTPSESSION hRTP)
{
rtpSession *s = (rtpSession *)hRTP;
if (s)
{
if (s->hRTCP)
rtcpClose(s->hRTCP);
/* Send udp data through specified socket to the local host */
rtpResume(hRTP);
if (s->eventHandler != NULL)
{
/* We're probably also in non-blocking mode */
RvSelectRemove(RvRtpGetSelectEngine(rvRtpInstance.selectEngine), &s->selectFd);
RvFdDestruct(&s->selectFd);
}
/* This function closes the specified IP socket and all the socket's connections.*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -