📄 rtp.c
字号:
#ifdef __cplusplus
extern "C" {
#endif
/*
NOTICE:
This document contains information that is proprietary to RADVision LTD.
No part of this publication may be reproduced in any form whatsoever without
written prior approval by RADVision LTD.
RADVision LTD. reserves the right to revise this publication and make changes
without obligation to notify any person of such revisions or changes.
*/
/****************************************************************************
rtp.c -- RTP implementation.
This Comment: 16-Mar-1997
Module Authors: Sasha Ruditsky, Oz Solomonovich
Abstract: The main RTP module file.
Platforms: All.
Known Bugs: None.
****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "rvcore.h"
#include "rvmem.h"
#include "rvtime.h"
#include "rvdefalloc.h"
#include "rvinet.h"
#include "rvhost.h"
#include "rvsocket.h"
#include "rvsocketaddr.h"
#ifdef _ATM_
#include "rvatm.h"
#endif
#include "bitfield.h"
#ifdef _ATM_
#include "liatm.h"
#endif
#include "rtpstd.h"
#include "rtputil.h"
#include "rtp.h"
#include "rtcp.h"
#ifdef _ATM_
#include "rtpatm.h"
#endif
#define BUILD_VER_NUM(major, minor, dot1, dot2) \
((RvUint32)((major << 24) + (minor << 16) + (dot1 << 8) + dot2))
#define VERSION_STR "2.2.0.3"
#define VERSION_NUM BUILD_VER_NUM(2, 2, 0, 3)
static rtpEngine* rtpDefaultEngine = NULL;
static RvHost host;
#ifdef _MTS_
static unsigned int seed;
#endif
static RvBool isMyIP(RvSocketAddr* addr)
{
size_t i;
for (i=0; i < rvHostGetNumOfAddrs(&host); i++)
{
if (rvIpv4AddrToUint32(rvSocketAddrGetIpv4Addr(addr)) ==
rvIpv4AddrToUint32(rvHostGetIpv4Addr(&host, i)))
return rvTrue;
}
return rvFalse;
}
/* == Basic RTP Functions == */
RVVXDAPI
RvInt32 VXDCALLCONV rtpInit(void)
{
RvTimespec t;
rvCoreInit();
rvTimeGetEpochTime(&t);
rvHostConstructLocal(&host);
#ifdef _MTS_
seed = (unsigned)(rvTimespecSecs(&t) * rvTimespecNsecs(&t)) * rvIpv4AddrToUint32(rvHostGetIpv4Addr(&host, 0));
#else
srand((unsigned)(rvTimespecSecs(&t) * rvTimespecNsecs(&t)) * rvIpv4AddrToUint32(rvHostGetIpv4Addr(&host, 0)));
#endif
return 0;
}
RVVXDAPI
RvInt32 VXDCALLCONV rtpInitEx(RvUint32 ip)
{
RvTimespec t;
rvCoreInit();
rvTimeGetEpochTime(&t);
rvHostConstructIpv4(&host, (RvIpv4Addr*)&ip);
#ifdef _MTS_
seed = (unsigned)(rvTimespecSecs(&t) * (rvTimespecNsecs(&t) + 1)) * rvIpv4AddrToUint32(rvHostGetIpv4Addr(&host, 0));
#else
srand((unsigned)(rvTimespecSecs(&t) * (rvTimespecNsecs(&t) + 1)) * rvIpv4AddrToUint32(rvHostGetIpv4Addr(&host, 0)));
#endif
return 0;
}
RVVXDAPI
void VXDCALLCONV rtpEnd(void)
{
rvHostDestruct(&host);
rvCoreEnd();
}
static void rtpReceive_(RvSocketSelect* ss, RvSocketListener* sl, void* data) {
rtpSession* s = (rtpSession*)data;
rvMutexLock(&s->mutex);
if (s->eventHandler)
s->eventHandler((HRTPSESSION)s, s->context);
rvMutexUnlock(&s->mutex);
}
RVVXDAPI
rtpEngine* VXDCALLCONV rtpEngineConstruct(rtpEngine* engine, RvPriority priority)
{
rvSocketEngineConstruct(engine, rvPriorityGetValue(&priority), &rvDefaultAlloc);
rtpDefaultEngine = engine;
rvSocketEngineStart(engine);
return engine;
}
RVVXDAPI
void VXDCALLCONV rtpEngineDestruct(rtpEngine* engine) {
rvSocketEngineDestruct(engine);
}
RVVXDAPI
int VXDCALLCONV rtpGetAllocationSize(void)
{
return sizeof(rtpSession);
}
RVVXDAPI
HRTPSESSION VXDCALLCONV rtpOpenFrom(
IN RvUint16 port,
IN RvUint32 ssrcPattern,
IN RvUint32 ssrcMask,
IN void* buffer,
IN int bufferSize)
{
rtpSession *s = (rtpSession *)buffer;
if (bufferSize < rtpGetAllocationSize())
return NULL;
memset(buffer, 0 , rtpGetAllocationSize());
s->isAllocated = rvFalse;
s->sSrcPattern = ssrcPattern;
s->sSrcMask = ssrcMask;
s->sequenceNumber = (RvUint16)0;
s->eventHandler = NULL;
s->engine = NULL;
#ifdef _MTS_
rand_r(&seed);
#else
rand();
#endif
rvMutexConstruct(&s->mutex);
/* If only one local interface bind to it, otherwise bind to "any" */
if (rvHostGetNumOfAddrs(&host) == 1) {
RvSocketAddr sa;
rvSocketAddrConstructInet(&sa, &host, 0, port);
rvSocketConstructUdpEx(&s->socket, &sa);
} else {
if(port == 0) {
rvSocketConstructUdpAnyPort(&s->socket); /* assign a port now */
} else rvSocketConstructUdp(&s->socket, port);
}
rtpRegenSSRC((HRTPSESSION)s);
rvSocketListenerConstruct(&s->listener, &s->socket, rtpReceive_, s);
return (HRTPSESSION)s;
}
RVVXDAPI
HRTPSESSION VXDCALLCONV rtpOpen(
IN RvUint16 port,
IN RvUint32 ssrcPattern,
IN RvUint32 ssrcMask)
{
return rtpOpenEx(port, ssrcPattern, ssrcMask, NULL);
}
RVVXDAPI
HRTPSESSION VXDCALLCONV rtpOpenEx(
IN RvUint16 port,
IN RvUint32 ssrcPattern,
IN RvUint32 ssrcMask,
IN char * cname)
{
rtpSession *s = (rtpSession*)rvMemAlloc(rtpGetAllocationSize());
if (s==NULL) return NULL;
memset(s, 0, rtpGetAllocationSize());
if ((rtpSession *)rtpOpenFrom(port, ssrcPattern, ssrcMask, (void*)s, rtpGetAllocationSize())==NULL)
{
rvMemFree(s);
return NULL;
}
s->isAllocated=rvTrue;
if (cname)
{
s->hRTCP = rtcpOpen(s->sSrc, (RvUint16)((port)?port+1:port), cname);
}
return (HRTPSESSION)s;
}
RVVXDAPI
RvUint32 VXDCALLCONV rtpClose(
IN HRTPSESSION hRTP)
{
rtpSession *s = (rtpSession *)hRTP;
if (s->hRTCP)
rtcpClose(s->hRTCP);
if (s->engine)
rvSocketEngineUnregisterListener(s->engine, &s->listener);
rvSocketListenerDestruct(&s->listener);
#if 0
{
RvHost h;
RvSocketAddr toAddr;
rvHostConstruct(&h, "127.0.0.1");
rvSocketAddrConstructInet(&toAddr, &h, 0, rvSocketGetPort(&s->socket));
rvSocketSendTo(&s->socket, (RvUint8*)"", 1, &toAddr);
}
#endif
rvSocketDestruct(&s->socket);
rvMutexDestruct(&s->mutex);
if (s->isAllocated)
rvMemFree(s);
return 0;
}
RVVXDAPI
RvUint32 VXDCALLCONV rtpGetSSRC(
IN HRTPSESSION hRTP)
{
rtpSession *s = (rtpSession *)hRTP;
return s->sSrc;
}
RVVXDAPI
void VXDCALLCONV rtpSetEventHandlerEx(
IN HRTPSESSION hRTP,
IN rtpEngine* engine,
IN LPRTPEVENTHANDLER eventHandler,
IN void* context)
{
rtpSession *s = (rtpSession *)hRTP;
if (s)
{
rvMutexLock(&s->mutex);
s->eventHandler = eventHandler;
s->context = context;
if (engine != NULL) {
s->engine = engine;
rvSocketEngineRegisterListener(s->engine, &s->listener);
}
rvMutexUnlock(&s->mutex);
}
}
RVVXDAPI
void VXDCALLCONV rtpSetEventHandler(
IN HRTPSESSION hRTP,
IN LPRTPEVENTHANDLER eventHandler,
IN void* context)
{
rtpSetEventHandlerEx(hRTP, rtpDefaultEngine, eventHandler, context);
}
RVVXDAPI
void VXDCALLCONV rtpSetRemoteAddress(
IN HRTPSESSION hRTP, /* RTP Session Opaque Handle */
IN RvUint32 ip,
IN RvUint16 port)
{
rtpSession *s = (rtpSession *)hRTP;
rvMutexLock(&s->mutex);
s->ip = ip;
s->port = port;
rvMutexUnlock(&s->mutex);
}
RVVXDAPI
RvInt32 VXDCALLCONV rtpWrite(
IN HRTPSESSION hRTP,
IN void * buf,
IN RvInt32 len,
IN rtpParam * p)
{
int retVal;
RvIpv4Addr ipv4;
RvSocketAddr toAddr;
rtpSession *s = (rtpSession *)hRTP;
RvUint32 *header=(RvUint32*)((char*)buf+p->sByte-12);
rvMutexLock(&s->mutex);
rvIpv4AddrConstruct(&ipv4, s->ip);
rvSocketAddrConstructIpv4(&toAddr, &ipv4, s->port);
if (s->useSequenceNumber)
s->sequenceNumber=p->sequenceNumber;
p->sequenceNumber=s->sequenceNumber;
header[0]=0;
header[0]=bitfieldSet(header[0],2,30,2);
header[0]=bitfieldSet(header[0],p->marker,23,1);
header[0]=bitfieldSet(header[0],p->payload,16,7);
header[0]=bitfieldSet(header[0],s->sequenceNumber++,0,16);
header[1]=p->timestamp;
header[2]=s->sSrc;
p->len=len-p->sByte;
ConvertToNetwork(header,0,3);
retVal = rvSocketSendTo(&s->socket, (RvUint8*)header,
len-((char*)header-(char*)buf), &toAddr);
if (s->hRTCP && retVal)
{
rtcpRTPPacketSent(s->hRTCP, p->len, p->timestamp);
}
rvMutexUnlock(&s->mutex);
return retVal;
}
RVVXDAPI
RvInt32 VXDCALLCONV rtpRead(
IN HRTPSESSION hRTP,
IN void *buf,
IN RvInt32 len,
OUT rtpParam* p)
{
rtpSession *s = (rtpSession *)hRTP;
RvSocketAddr fromAddr;
RvUint32 *header=(RvUint32*)buf;
p->len=rvSocketRecvFrom(&s->socket,(unsigned char*)buf,len,&fromAddr);
if (p->len <= 0)
return p->len;
rvMutexLock(&s->mutex);
ConvertFromNetwork(buf,0,3);
if((isMyIP(&fromAddr) && s->sSrc==((RvUint32*)buf)[2]) || p->len == -1 || p->len < 12)
{
rvMutexUnlock(&s->mutex);
return (-1);
}
ConvertFromNetwork(buf,3,bitfieldGet(header[0],24,4));
p->timestamp=header[1];
p->sequenceNumber=(RvUint16)bitfieldGet(header[0],0,16);
p->sSrc=header[2];
p->marker=bitfieldGet(header[0],23,1);
p->payload=(unsigned char)bitfieldGet(header[0],16,7);
p->sByte=12+bitfieldGet(header[0],24,4)*sizeof(RvUint32);
if (bitfieldGet(header[0],28,1))/*Extension Bit Set*/
{
int xStart=p->sByte/sizeof(RvUint32);
ConvertFromNetwork(buf,xStart,1);
ConvertFromNetwork(buf,xStart+1,bitfieldGet(header[xStart],0,16));
p->sByte+=bitfieldGet(header[xStart],0,16)*sizeof(RvUint32);
}
if (bitfieldGet(header[0],29,1))/*Padding Bit Set*/
{
p->len-=((char*)buf)[p->len-1];
}
rvMutexUnlock(&s->mutex);
return 0;
}
RVVXDAPI
RvInt32 VXDCALLCONV rtpReadEx(
IN HRTPSESSION hRTP,
IN void * buf,
IN RvInt32 len,
IN RvUint32 timestamp,
OUT rtpParam * p)
{
rtpSession *s = (rtpSession *)hRTP;
int retVal;
rvMutexLock(&s->mutex);
retVal = rtpRead(hRTP, buf, len, p);
if (s->hRTCP && retVal >= 0)
{
rtcpRTPPacketRecv(s->hRTCP, p->sSrc, timestamp, p->timestamp, p->sequenceNumber);
}
rvMutexUnlock(&s->mutex);
return retVal;
}
RVVXDAPI
RvUint16 VXDCALLCONV rtpGetPort(
IN HRTPSESSION hRTP) /* RTP Session Opaque Handle */
{
RvUint16 port;
rtpSession *s = (rtpSession *)hRTP;
rvMutexLock(&s->mutex);
port = rvSocketGetPort(&s->socket);
rvMutexUnlock(&s->mutex);
return port;
}
RVVXDAPI
char * VXDCALLCONV rtpGetVersion(void)
{
return (char*)VERSION_STR;
}
RVVXDAPI
RvUint32 VXDCALLCONV rtpGetVersionNum(void)
{
return VERSION_NUM;
}
/* == ENDS: Basic RTP Functions == */
/* == Accessory RTP Functions == */
RVVXDAPI
HRTCPSESSION VXDCALLCONV rtpGetRTCPSession(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -