/****************************************************************************** * FILE: RtpApp.cpp * Description: * Implement for CRtpApp class. * * Modified Code History * Mark Date By Modification Reason ******************************************************************************* * 01 2008-4-16 songxw Initial creation. ******************************************************************************/ #include #include #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; }