/****************************************************************************** * FILE: RtspClient.cpp * Description: * Implement for CRtspClient class. * * Modified Code History * Mark Date By Modification Reason ******************************************************************************* * 01 2013/5/28 songxw Initial creation. ******************************************************************************/ #include #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 (and perhaps ). 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; }