/******************************************************************************
|
* FILE: RtpApp.cpp
|
* Description:
|
* Implement for CRtpApp class.
|
*
|
* Modified Code History
|
* Mark Date By Modification Reason
|
*******************************************************************************
|
* 01 2008-4-16 songxw Initial creation.
|
******************************************************************************/
|
|
#include <sys/time.h>
|
#include <unistd.h>
|
#include "RtpApp.h"
|
|
CRtpApp::CRtpApp()
|
{
|
tsunit = 1.0 / 90000;
|
|
struct timezone tzone;
|
gettimeofday(&RunTime, &tzone);
|
gettimeofday(&RunTime2, &tzone);
|
SeqNum = 0;
|
SendTimeForNAT = 0;
|
}
|
CRtpApp::~CRtpApp()
|
{
|
|
}
|
|
/******************************************************************************
|
* Function:
|
* Create rtp session and be ready for receiving data.
|
******************************************************************************/
|
int CRtpApp::CreateSession(UINT16 ListenPort, UINT32 nSsrc, bool usethread)
|
{
|
SessParams.SetUsePollThread(usethread);
|
SessParams.SetOwnTimestampUnit(tsunit);
|
SessParams.SetAcceptOwnPackets(true);
|
TransParams.SetPortbase(ListenPort);
|
|
SessParams.SetMaximumPacketSize(60*1024);
|
if(nSsrc > 0)
|
{
|
SessParams.SetUsePredefinedSSRC(true);
|
SessParams.SetPredefinedSSRC(nSsrc);
|
}
|
|
int iErrNum = Create(SessParams, &TransParams);
|
if (iErrNum < 0)
|
{
|
string RtpError = RTPGetErrorString(iErrNum);
|
DBGPrint(M_RtpSessMgr, ERROR_LEVEL, "Create RTP Session error! Reason: %s!", RtpError.c_str() );
|
return -1;
|
}
|
|
SetDefaultPayloadType(0);
|
SetDefaultMark(false);
|
SetDefaultTimestampIncrement(0);
|
// IncrementTimestampDefault();
|
// IncrementTimestamp(1);
|
|
return 0;
|
}
|
|
/******************************************************************************
|
* Function:
|
* Set source ip address, port and session ID. Send several packets to traverse
|
* NAT.
|
******************************************************************************/
|
int CRtpApp::NatMappingControl(char IpStr[], UINT16 port, int SSId)
|
{
|
SessionID = SSId;
|
|
RTPIPv4Address RtpAddr( ntohl(inet_addr(IpStr) ), port);
|
int iErrNum = AddDestination(RtpAddr);
|
if (iErrNum != 0)
|
{
|
string RtpError = RTPGetErrorString(iErrNum);
|
DBGPrint(M_RtpSessMgr, ERROR_LEVEL, "AddDestination <%s: %d> fail! Reason: %s!", IpStr, port, RtpError.c_str() );
|
return -1;
|
}
|
|
SendNatMappingPacket();
|
usleep(1000);
|
SendNatMappingPacket();
|
usleep(1000);
|
SendNatMappingPacket();
|
|
return 0;
|
}
|
|
/******************************************************************************
|
* Function:
|
* Hook function of receiving a rtp packet.
|
******************************************************************************/
|
void CRtpApp::CBRtpRecv()
|
{
|
|
}
|
|
/******************************************************************************
|
* Function:
|
* Rtp session data poll function.
|
******************************************************************************/
|
void CRtpApp::OnPollThreadStep()
|
{
|
CBRtpRecv();
|
}
|
|
/******************************************************************************
|
* Function:
|
* Bye operation of rtp session.
|
******************************************************************************/
|
void CRtpApp::RtpDestroy()
|
{
|
BYEDestroy(RTPTime(1, 0), 0, 0);
|
}
|
|
/******************************************************************************
|
* Function:
|
* Send a packet to traverse NAT and keep mapping status to let rtp data come.
|
******************************************************************************/
|
void CRtpApp::SendNatMappingPacket(void)
|
{
|
UINT8 data[48+1] = {0};
|
|
//Set version and payload type
|
data[0] = 0x80;
|
data[1] = 0x30; //Mark is always true. 0xb0 = 0x80 + 0x30
|
|
//Set sequence number
|
*( (UINT16 *)&data[2] ) = htons(SeqNum++);
|
|
struct timeval CurrTVal;
|
struct timezone tzone;
|
gettimeofday(&CurrTVal, &tzone);
|
int timestamp = (CurrTVal.tv_sec - RunTime.tv_sec) * 1000 + (CurrTVal.tv_usec - RunTime.tv_usec) / 1000; //(ms)
|
|
//Set timestamp
|
*( (UINT32 *)&data[4] ) = htonl(timestamp);
|
|
//Set SSRC
|
*( (UINT32 *)&data[8] ) = htonl(SessionID);
|
|
//Set payload data
|
snprintf( (char *)&data[12], 36, "%s", "A Packet to traverse NAT.");
|
|
SendPacketIntegratedData(data, 48);
|
}
|
|
int CRtpApp::GetTimeStamp(void)
|
{
|
struct timeval CurrTVal;
|
struct timezone tzone;
|
gettimeofday(&CurrTVal, &tzone);
|
int timestamp = (CurrTVal.tv_sec - RunTime.tv_sec) * 1000 + (CurrTVal.tv_usec - RunTime.tv_usec) / 1000; //(ms)
|
|
/*
|
printf("timestamp = %d, CurrTVal(%d %d), RunTime(%d %d), CurrTVal.tv_sec - RunTime.tv_sec = %d, CurrTVal.tv_usec - RunTime.tv_usec = %d\n", timestamp, \
|
CurrTVal.tv_sec, CurrTVal.tv_usec, RunTime.tv_sec, RunTime.tv_usec, CurrTVal.tv_sec - RunTime.tv_sec, CurrTVal.tv_usec - RunTime.tv_usec);
|
*/
|
|
if (timestamp != 0)
|
{
|
RunTime = CurrTVal;
|
}
|
|
return timestamp;
|
}
|
|
int CRtpApp::GetAudioTimeStamp(void)
|
{
|
struct timeval CurrTVal;
|
struct timezone tzone;
|
gettimeofday(&CurrTVal, &tzone);
|
int timestamp = (CurrTVal.tv_sec - RunTime2.tv_sec) * 1000 + (CurrTVal.tv_usec - RunTime2.tv_usec) / 1000; //(ms)
|
|
// printf("----------------CurrTVal(%d %d) and RunTime2(%d %d) from RunTime3(%d %d), timestamp = %d \n", CurrTVal.tv_sec, CurrTVal.tv_usec, RunTime2.tv_sec, RunTime2.tv_usec, RunTime3.tv_sec, RunTime3.tv_usec, timestamp);
|
|
if (timestamp != 0)
|
{
|
RunTime2 = CurrTVal;
|
}
|
|
return timestamp;
|
}
|