/******************************************************************************
|
* FILE: RtspClient.cpp
|
* Description:
|
* Implement for CRtspClient class.
|
*
|
* Modified Code History
|
* Mark Date By Modification Reason
|
*******************************************************************************
|
* 01 2013/5/28 songxw Initial creation.
|
******************************************************************************/
|
|
#include <poll.h>
|
#include "RtspClient.h"
|
|
CRtspClient::CRtspClient(void)
|
{
|
m_pRCSession = NULL;
|
}
|
|
CRtspClient::~CRtspClient(void)
|
{
|
if (m_pRCSession != NULL)
|
{
|
m_pRCSession->Teardown(m_pRCSession->SessionID, m_pRCSession->StrVStream);
|
SAFE_DELETE(m_pRCSession);
|
}
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
// º¯ÊýÃû£ºOpenRtspStream
|
// ÃèÊö£ºÉèÖûص÷º¯Êý¡£
|
// ²ÎÊý£ºrtspµØÖ·¡¢ ÂëÁ÷»Øµ÷º¯Êý¡¢Óû§Ö¸Õë
|
//
|
//
|
// ·µ»ØÖµ£º
|
// ¡£
|
// ˵Ã÷£º
|
// ±£ÁôÔÄ£¿é½Ó¿Ú¡£
|
////////////////////////////////////////////////////////////////////////////////
|
long CRtspClient::OpenRtspStream(const char *RtspUrl, PlayCallBack2 PlayCBFunc, long UserData)
|
{
|
if(NULL == RtspUrl || strlen(RtspUrl) < 7) //rtsp://
|
{
|
printf("%s: rtspurl:%s is error!!!", __FUNCTION__, RtspUrl);
|
return RTSP_ERR_PARAM;
|
}
|
|
//½âÎöRtspUrlµÄÓû§Ãû ¡¢ÃÜÂë¡¢ip¡¢port
|
//-------------------------------------------------
|
char const* prefix = "rtsp://";
|
unsigned const prefixLength = 7;
|
if (strncasecmp(RtspUrl, prefix, prefixLength) != 0)
|
{
|
printf("%s: rtspurl:%s is error!!!", __FUNCTION__, RtspUrl);
|
return RTSP_ERR_PARAM;
|
}
|
char username[64+1] = {0};
|
char passwd[64+1] = {0};
|
char url[256+1] = {0};
|
bool bsetauth = false;
|
char const* colonPasswordStart = NULL;
|
//char const* from = RtspUrl+7; //Ìø¹ýÍ·
|
char const* from = &RtspUrl[prefixLength];
|
char const* p = NULL;
|
for (p=from; *p != '\0' && *p != '/'; ++p)
|
{
|
if (*p == ':' && colonPasswordStart == NULL)
|
{
|
colonPasswordStart = p;
|
}
|
else if (*p == '@')
|
{
|
// We found <username> (and perhaps <password>). Copy them into newly-allocated result strings:
|
if (colonPasswordStart == NULL)
|
{
|
colonPasswordStart = p;
|
}
|
|
char const* usernameStart = from;
|
unsigned int usernameLen = colonPasswordStart - usernameStart;
|
memcpy(username, usernameStart, usernameLen);
|
|
char const* passwordStart = colonPasswordStart;
|
if (passwordStart < p)
|
{
|
++passwordStart; // skip over the ':'
|
}
|
unsigned passwordLen = p - passwordStart;
|
memcpy(passwd, passwordStart, passwordLen);
|
|
from = p + 1; // skip over the '@'
|
sprintf(url, "rtsp://%s", from);
|
|
printf("%s:1.++++++++++++++++rtspURL:%s, username:%s, passwd:%s, url:%s\n", __FUNCTION__, RtspUrl, username, passwd, url);
|
bsetauth = true;
|
break;
|
}
|
}
|
unsigned const parseBufferSize = 100;
|
char parseBuffer[parseBufferSize];
|
char* to = &parseBuffer[0];
|
unsigned i;
|
for (i = 0; i < parseBufferSize; ++i)
|
{
|
if (*from == '\0' || *from == ':' || *from == '/')
|
{
|
// We've completed parsing the address
|
*to = '\0';
|
break;
|
}
|
*to++ = *from++;
|
}
|
if (i == parseBufferSize)
|
{
|
printf("URL is too long");
|
return RTSP_ERR_PARAM;
|
}
|
char ipAddr[32+1] = {0};
|
memcpy(ipAddr, parseBuffer, strlen(parseBuffer));
|
|
int portNum = 554; // default value
|
char nextChar = *from;
|
if (nextChar == ':')
|
{
|
int portNumInt;
|
if (sscanf(++from, "%d", &portNumInt) != 1)
|
{
|
printf("No port number follows ':'");
|
return RTSP_ERR_PARAM;
|
}
|
if (portNumInt < 1 || portNumInt > 65535)
|
{
|
printf("Bad port number");
|
return RTSP_ERR_PARAM;
|
}
|
portNum = (unsigned short)portNumInt;
|
while (*from >= '0' && *from <= '9')
|
++from; // skip over port number
|
}
|
if (strlen(url) < 7)
|
{
|
memcpy(url, RtspUrl, strlen(RtspUrl));
|
}
|
printf("%s:2.++++++++++++++++rtspURL:%s, username:%s, passwd:%s, ip:%s, port:%d url:%s\n", __FUNCTION__, RtspUrl, username, passwd, ipAddr, portNum, url);
|
//-------------------------------------------------------------------
|
|
//½âÎöRtspUrlµÄÂëÁ÷´«ÊäÀàÐͺÍÇëÇóÊÓÆµÀàÐÍ
|
CRtspRequestMsg ReqMsg;
|
CString StrRtspUrl = url;
|
ReqMsg.SetUrl(StrRtspUrl);
|
ReqMsg.ParserUri();
|
printf("%s:3.++++++++++++++++rtspURL:%s, DevAor:%s, StreamType:%d, PlayType:%d, BeginTime:%s, EndTime:%s\n", __FUNCTION__, \
|
url, ReqMsg.UrlParam.DevAor, ReqMsg.UrlParam.StreamType, ReqMsg.UrlParam.Type, ReqMsg.UrlParam.BeginTime, ReqMsg.UrlParam.EndTime);
|
|
if (m_pRCSession == NULL)
|
{
|
m_pRCSession = new CRtspClientSession();
|
if (NULL == m_pRCSession)
|
{
|
printf("%s: failed: no memory!", __FUNCTION__);
|
return RTSP_ERR_NO_MEMORY;
|
}
|
}
|
m_pRCSession->SetRtspSessionInfo(url, username, passwd, bsetauth);
|
|
StreamTransType_E eStreamType = E_STREAM_TRANS_UDP;
|
if (ReqMsg.UrlParam.StreamType == (int)E_STREAM_TRANS_TCPACTIVE || ReqMsg.UrlParam.StreamType == (int)E_STREAM_TRANS_TCPPASSIVE)
|
{
|
eStreamType = (StreamTransType_E)ReqMsg.UrlParam.StreamType;
|
}
|
|
m_pRCSession->pTcpTransport = new CTcpTransport(ipAddr, portNum);
|
if(NULL == m_pRCSession->pTcpTransport)
|
{
|
printf("%s: pTcpTransport is null pointer!", __FUNCTION__);
|
SAFE_DELETE(m_pRCSession);
|
return -1;
|
}
|
int iRet = m_pRCSession->pTcpTransport->Create();
|
if (-1 == iRet)
|
{
|
printf("%s: not connect to Dev<%s:%d>!", __FUNCTION__, m_pRCSession->pTcpTransport->sIpAddr, m_pRCSession->pTcpTransport->uPort);
|
SAFE_DELETE(m_pRCSession->pTcpTransport);
|
SAFE_DELETE(m_pRCSession);
|
return RTSP_ERR_CONNECT;
|
}
|
|
//1.·¢ËÍOptions
|
iRet = m_pRCSession->Options(url);
|
if (-1 == iRet)
|
{
|
printf("Options Rtsp client session Failed, Url: %s!", url);
|
StopRtspStream();
|
return RTSP_ERR_OPTIONS;
|
}
|
printf("1.>>>>>>>>>>>>>>>>send option sucess! rtspurl:%s\n", url);
|
|
//2.»ñȡýÌåÃèÊöÐÅÏ¢
|
iRet = m_pRCSession->Describe(url);
|
if (-1 == iRet)
|
{
|
printf("Describe Rtsp client session Failed, Url: %s!", url);
|
StopRtspStream();
|
return RTSP_ERR_DESCRIBE;
|
}
|
printf("2.>>>>>>>>>>>>>>>>send describe sucess! rtspurl:%s\n", url);
|
|
//3.·¢ËÍ´øÈÏÖ¤µÄDescribe
|
if (bsetauth == true)
|
{
|
iRet = m_pRCSession->Describe(url, bsetauth);
|
if (-1 == iRet)
|
{
|
printf("Describe Rtsp client session Failed, Url: %s!", url);
|
StopRtspStream();
|
return RTSP_ERR_DESCRIBE;
|
}
|
printf("3.>>>>>>>>>>>>>>>>send auth describe sucess! rtspurl:%s\n", url);
|
}
|
m_pRCSession->StrVStream = m_pRCSession->CnxData.StrVStream;
|
m_pRCSession->StrAStream = m_pRCSession->CnxData.StrAStream;
|
|
//Èç¹ûÊÇtcpserver £¬ ÐèÒªÌáǰ´´½¨tcpserver
|
bool bCreateTcpSvr = false;
|
#if 0
|
if (eStreamType == E_STREAM_TRANS_TCPPASSIVE)
|
{
|
if (m_pRCSession->m_pTcpStreamTrans == NULL)
|
{
|
m_pRCSession->m_pTcpStreamTrans = new CTcpStreamTrans();
|
m_pRCSession->m_pTcpStreamTrans->SetStreamCallBackParam(PlayCBFunc, UserData);
|
bCreateTcpSvr = true;
|
}
|
}
|
#endif
|
if (eStreamType == E_STREAM_TRANS_UDP)
|
{
|
//udp recv stream
|
if (m_pRCSession->m_pUdpStreamTrans == NULL)
|
{
|
m_pRCSession->m_pUdpStreamTrans = new CUdpStreamTrans();
|
}
|
//ÉèÖûص÷ÐÅÏ¢
|
m_pRCSession->m_pUdpStreamTrans->SetStreamCallBackParam(PlayCBFunc, UserData);
|
}
|
//4.½¨Á¢Òô¡¢ÊÓÆµ»á»°ÐÅÁîÁ¬½Ó(±¸×¢£ºÊÓÆµ»á»°Ä¬È϶¼ÐèÒª½¨Á¢£¬ÄÄÅÂûÓÐÊÓÆµÁ÷ID¡£)
|
iRet = m_pRCSession->Setup(m_pRCSession->SessionID, m_pRCSession->StrVStream, bCreateTcpSvr);
|
if (-1 == iRet)
|
{
|
printf("Setup client session Failed, Url: %s!\n", url);
|
StopRtspStream();
|
return RTSP_ERR_SETUP;
|
}
|
printf("4.>>>>>>>>>>>>>>>>send setup sucess! rtspurl:%s\n", url);
|
|
//Õë¶ÔSessionID ¸³Öµ
|
if ( !m_pRCSession->CnxData.SessionID.IsEmpty() )
|
{
|
m_pRCSession->SessionID = m_pRCSession->CnxData.SessionID;
|
}
|
|
if (eStreamType == E_STREAM_TRANS_TCPACTIVE || eStreamType == E_STREAM_TRANS_TCPPASSIVE)
|
{
|
//tcp recv stream
|
if (m_pRCSession->m_pTcpStreamTrans == NULL)
|
{
|
m_pRCSession->m_pTcpStreamTrans = new CTcpStreamTrans();
|
}
|
//ÉèÖòÎÊý
|
m_pRCSession->m_pTcpStreamTrans->SetStreamTransParam(eStreamType, m_pRCSession->CnxData.strServerIp.c_str(), m_pRCSession->CnxData.ServerPort, m_pRCSession->CnxData.strClientIp.c_str(), m_pRCSession->CnxData.ClientPort);
|
//ÉèÖûص÷ÐÅÏ¢
|
m_pRCSession->m_pTcpStreamTrans->SetStreamCallBackParam(PlayCBFunc, UserData);
|
|
//¿ªÆôÏß³Ì
|
if (m_pRCSession->m_pTcpStreamTrans->IsRunning() == false)
|
{
|
m_pRCSession->m_pTcpStreamTrans->Start();
|
}
|
}
|
else
|
{
|
|
}
|
|
//5.²¥·Å
|
iRet = m_pRCSession->Play(m_pRCSession->SessionID);
|
if (-1 == iRet)
|
{
|
printf("%s: Play fail for Url<%s>!", __FUNCTION__, (char*)(CPCHAR)m_pRCSession->CnxData.StrUrl);
|
StopRtspStream();
|
return RTSP_ERR_PLAY;
|
}
|
printf("5.>>>>>>>>>>>>>>>>send play sucess! rtspurl:%s\n", url);
|
#if 0
|
//²¥·Å³É¹¦ÐèÒªÆô¶¯Ï߳̽øÐÐÐÒé±¥ºÍ
|
if (m_pRCSession->IsRunning() == false)
|
{
|
m_pRCSession->Start();
|
}
|
#endif
|
return RTSP_ERR_OK;
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
// º¯ÊýÃû£ºRtspContrl
|
// ÃèÊö£ºµã²¥¿ØÖÆÀàÐÍ ºÍµã²¥¿ØÖƲÎÊý
|
// ²ÎÊý£º
|
//
|
//
|
// ·µ»ØÖµ£º
|
// ¡£
|
// ˵Ã÷£º
|
// ±£ÁôÔÄ£¿é½Ó¿Ú¡£
|
////////////////////////////////////////////////////////////////////////////////
|
long CRtspClient::RtspContrl(int ctrltype, double ctrlparam)
|
{
|
switch(ctrltype)
|
{
|
case HIS_VIDEO_CTRL_PLAY:
|
case HIS_VIDEO_CTRL_FAST:
|
case HIS_VIDEO_CTRL_SLOW:
|
case HIS_VIDEO_CTRL_JUMP:
|
{
|
m_pRCSession->Play(m_pRCSession->SessionID, ctrltype, ctrlparam);
|
}
|
break;
|
case HIS_VIDEO_CTRL_PAUSE:
|
{
|
m_pRCSession->Pause(m_pRCSession->SessionID);
|
}
|
break;
|
default:
|
printf("%s:%d can't find ctrltype<%d>!\n", __FUNCTION__, __LINE__, ctrltype);
|
return RTSP_ERR_PARAM;
|
}
|
|
return RTSP_ERR_OK;
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
// º¯ÊýÃû£ºStopRtspStream
|
// ÃèÊö£ºÍ£Ö¹RTSP»á»°
|
// ²ÎÊý£º
|
//
|
//
|
// ·µ»ØÖµ£º
|
// ¡£
|
// ˵Ã÷£º
|
// ±£ÁôÔÄ£¿é½Ó¿Ú¡£
|
////////////////////////////////////////////////////////////////////////////////
|
long CRtspClient::StopRtspStream(void)
|
{
|
if (m_pRCSession != NULL)
|
{
|
printf("StopRtspStream, m_pRCSession != NULL\n");
|
int iRet = -1;
|
//Èç¹û´æÔÚÒôƵ
|
CString StrTearDown;
|
if(false == m_pRCSession->bAudio)
|
{
|
StrTearDown = m_pRCSession->StrVStream;
|
}
|
iRet = m_pRCSession->Teardown(m_pRCSession->SessionID, StrTearDown);
|
if(iRet < 0)
|
{
|
//ʧ°Ü²»·µ»Ø
|
printf("%s: Teardown Failed for url<%s>!\n", __FUNCTION__, (char*)(CPCHAR)m_pRCSession->CnxData.StrUrl);
|
}
|
else
|
{
|
printf("%s: Teardown Sucess for url<%s>!\n", __FUNCTION__, (char*)(CPCHAR)m_pRCSession->CnxData.StrUrl);
|
}
|
printf("StopRtspStream, before SAFE_DELETE\n");
|
SAFE_DELETE(m_pRCSession);
|
printf("StopRtspStream, SAFE_DELETE\n");
|
|
}
|
|
return RTSP_ERR_OK;
|
}
|
|
|