⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtspclnt.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		// create an RTCP transport for this stream
		RTCPUDPTransport* pRTCPTran = new RTCPUDPTransport(m_bSetupRecord);
                if(!pRTCPTran)
                {
                    HX_DELETE(pHeader);
                    HX_RELEASE(pTrans);
		    m_pMutex->Unlock();
                    return HXR_OUTOFMEMORY;
                }
		pRTCPTran->AddRef();
		pRTCPTran->init(m_pContext,
				pRTCPSocket,
				(RTPUDPTransport*)pTrans,
				(IHXRTSPTransportResponse*) this,
				streamNumber);

		((RTPUDPTransport*)pTrans)->setRTCPTransport(pRTCPTran);

		status = pRequest->addTransportInfo(pTrans, (RTCPBaseTransport*)pRTCPTran, streamNumber,
		    nUDPPort);

		if (m_bIPTV && m_pSetupRequestHeader && status != HXR_OUTOFMEMORY)
		{
		    addRFC822Headers(pMsg, m_pSetupRequestHeader);
		    // don't add it twice...
		    pIHXValuesRequestHeaders = NULL;
		}
	    }
	    break;

	    case RTSP_TR_RTP_TCP:
	    {
		RTSPTransport* pTrans = new RTPTCPTransport(m_bSetupRecord);
                if(!pTrans)
                {
                    HX_DELETE(pHeader);
                    return HXR_OUTOFMEMORY;
                }
		pTrans->AddRef();

		if (m_bPrefetch)
		{
		    pTrans->EnterPrefetch();
		}

		if (HXR_OK != ((RTPTCPTransport*)pTrans)->init(
                    m_pContext, m_pSocket, (IHXRTSPTransportResponse*)this))
		{
		    status = HXR_BAD_TRANSPORT;
		}

	    	// create an RTCP transport for this stream
	    	RTCPTCPTransport* pRTCPTran = new RTCPTCPTransport(m_bSetupRecord);
                if(!pRTCPTran)
                {
                    HX_DELETE(pHeader);
                    HX_DELETE(pTrans);
                    return HXR_OUTOFMEMORY;
                }
	    	pRTCPTran->AddRef();
	    	pRTCPTran->init(m_pContext,
			    	m_pSocket,
			    	(RTPTCPTransport*)pTrans,
			    	(IHXRTSPTransportResponse*)this,
			    	streamNumber);

	    	((RTPTCPTransport*)pTrans)->setRTCPTransport((RTCPBaseTransport*)pRTCPTran);

	    	status = pRequest->addTransportInfo(pTrans, (RTCPBaseTransport*)pRTCPTran, streamNumber,
		    	nUDPPort);

		if (m_bIPTV && m_pSetupRequestHeader)
		{
		    addRFC822Headers(pMsg, m_pSetupRequestHeader);
		    // don't add it twice...
		    pIHXValuesRequestHeaders = NULL;
		}
	    }
	    break;

	    default:
	    {
	    }
	    break;
	}
#endif /* HELIX_FEATURE_RTP */

	char* pModifiedMimeType = NULL;
	const char* pMimeType =
	    RTSPTransportMimeMapper::getTransportMimeType
	    (
		pRequest->m_lTransportType
	    );


	// Accomodate incompliant servers that understand only upper case
	// transport mime-types
	if (m_bForceUCaseTransportMimeType)
	{
	    ULONG32 ulMimeTypeLength = strlen(pMimeType);

	    if (ulMimeTypeLength != 0)
	    {
		pModifiedMimeType = new char [ulMimeTypeLength + 1];
                if(!pModifiedMimeType)
                {
                    HX_DELETE(pHeader);
                    return HXR_OUTOFMEMORY;
                }
	    }

	    if (pModifiedMimeType)
	    {
		strcpy(pModifiedMimeType, pMimeType); /* Flawfinder: ignore */
		StrToUpper(pModifiedMimeType);
		pMimeType = pModifiedMimeType;
	    }
	}

#if defined(HELIX_FEATURE_RTP)
	switch(pRequest->m_lTransportType)
	{
	    case RTSP_TR_RTP_UDP:
	    case RTSP_TR_RTP_TCP:
	    {
		char portValue[32]; /* Flawfinder: ignore */

		MIMEHeaderValue* pHeaderValue = new MIMEHeaderValue(pMimeType);

                if(!pHeaderValue)
                {
                    HX_DELETE(pHeader);
                    HX_DELETE(pModifiedMimeType);
                    return HXR_OUTOFMEMORY;
                }

                if (RTSP_TR_RTP_UDP == pRequest->m_lTransportType)
                {
		    SafeSprintf(portValue, 32, "%u-%u", nUDPPort, nUDPPort+1);
		    pHeaderValue->addParameter("client_port", (const char*)portValue);
#ifdef XXXtbradleyTEST_RTSP_DESTINATION
                    pHeaderValue->addParameter("destination", "127.0.0.1");
#endif /* XXXtbradleyTEST_RTSP_DESTINATION */
                }

                if(m_bSetupRecord)
		{
		    pHeaderValue->addParameter("mode", "record");
		}
		else
		{
		    pHeaderValue->addParameter("mode", "play");
		}
		pHeader->addHeaderValue(pHeaderValue);
	    }
	    break;

	    case RTSP_TR_RTP_MCAST:
            default:
	    {
	    }
	    break;
	}
#endif /* HELIX_FEATURE_RTP */

	HX_VECTOR_DELETE(pModifiedMimeType);
    }
    pMsg->addHeader(pHeader);

    return status;
}

STDMETHODIMP
RTSPClientProtocol::SendPlayRequest(UINT32 lFrom, UINT32 lTo,
    CHXSimpleList* pASMRules)
{
    /*
     * Flush the data packets out of the transport buffers
     */

    m_pMutex->Lock();

    m_bPaused = FALSE;

#if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
    if (m_bSDPInitiated && m_bMulticast)
    {
        m_pMutex->Unlock();
        return m_pResp->HandlePlayResponse(HXR_OK);
    }
#endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */

    /*
     * XXXGH...I believe we should be iterating through m_transportRequestList
     *         here and for SendPauseRequest, SendResumeRequest, etc.
     */

    // only used when m_bNonRSRTP is TRUE
    m_bPlayJustSent = TRUE;

    if (!m_transportRequestList.IsEmpty())
    {
	RTSPTransportRequest* pRequest =
	    (RTSPTransportRequest*)m_transportRequestList.GetHead();
	RTSPTransportInfo* pTransInfo = pRequest->getFirstTransportInfo();
	while(pTransInfo)
	{
	    pTransInfo->m_pTransport->playReset();
	    // set the range in transport...only for RTP
	    pTransInfo->m_pTransport->setPlayRange(lFrom, lTo);
            pTransInfo->m_pTransport->SetPlayRequestSent(TRUE);
	    pTransInfo->m_pTransport->resumeBuffers();
	    pTransInfo = pRequest->getNextTransportInfo();
	}
    }

    HX_RESULT rc = HXR_OK;
    RTSPPlayMessage* pMsg = new RTSPPlayMessage;
    if(pMsg)
    {
        RTSPRange range(lFrom, lTo, RTSPRange::TR_NPT);

        pMsg->setURL(m_url);
        AddCommonHeaderToMsg(pMsg);

        pMsg->addHeader("Range", (const char*)range.asString());
        UINT32 seqNo = m_pSession->getNextSeqNo(this);

        rc = sendRequest(pMsg, seqNo);
    }
    else
    {
        rc = HXR_OUTOFMEMORY;
    }
    m_pMutex->Unlock();
    return rc;
}

STDMETHODIMP
RTSPClientProtocol::SendRecordRequest()
{
    if (!m_pIsMethodSupported[RECORD] || !m_pSession)
    {
	return HXR_OK;
    }

    HX_RESULT rc = HXR_OK;
    m_pMutex->Lock();
    // Declaring these here so I can use a goto below!
    CHXString streamSequenceNumbers;
    BOOL bIsFirst = TRUE;
    CHXMapLongToObj::Iterator i;

    RTSPRecordMessage* pMsg = new RTSPRecordMessage;
    if(!pMsg)
    {
        rc =  HXR_OUTOFMEMORY;
        goto overandout;
    }

    pMsg->setURL(m_url);
    AddCommonHeaderToMsg(pMsg);

    /*
     * Add header for sequence numbers
     */

    for(i=m_pTransportStreamMap->Begin(); i!=m_pTransportStreamMap->End(); ++i)
    {

	int lenTmpBuf = 100 + strlen(m_url);
	char* tmpBuf = new char[lenTmpBuf];
        if(!tmpBuf)
        {
            HX_DELETE(pMsg);
            rc =  HXR_OUTOFMEMORY;
            goto overandout;
        }

	RTSPTransport* pTransport = (RTSPTransport*)(*i);
	pTransport->m_bHackedRecordFlag = TRUE;
	UINT16 streamNumber = (UINT16)i.get_key();
	UINT16 seqNum = pTransport->getSeqNum(streamNumber);
	UINT32 ulTimestamp = pTransport->getTimestamp(streamNumber);
	SafeSprintf(tmpBuf, lenTmpBuf, "url=" + m_url +
	    "/streamid=%d;seq=%d;rtptime=%ld", streamNumber, seqNum,
	    ulTimestamp);
	if(!bIsFirst)
	{
	    streamSequenceNumbers += ", " + CHXString(tmpBuf);
	}
	else
	{
	    bIsFirst = FALSE;
	    streamSequenceNumbers = tmpBuf;
	}

	delete[] tmpBuf;
    }
    pMsg->addHeader("RTP-Info", streamSequenceNumbers);
    if( m_pSession )
    {
        UINT32 seqNo = m_pSession->getNextSeqNo(this);
        rc = sendRequest(pMsg, seqNo);
    }
overandout:
    m_pMutex->Unlock();
    return rc;
}

STDMETHODIMP
RTSPClientProtocol::SendPauseRequest()
{
    m_bPaused = TRUE;

    /*
     * Stop the internal buffer timers
     */
    if (!m_pIsMethodSupported[PAUSE] || m_transportRequestList.IsEmpty() ||
        !m_pSession)
    {
	return HXR_OK;
    }

    m_pMutex->Lock();

    // only used when m_bNonRSRTP is TRUE
    m_bPlayJustSent = FALSE;

    SendMsgToTransport(PAUSE_BUFFER);

    HX_RESULT rc = SendMsgToServer(RTSP_PAUSE);

    m_pMutex->Unlock();
    return rc;
}

STDMETHODIMP
RTSPClientProtocol::SendResumeRequest()
{
    m_bPaused = FALSE;

    if (!m_pSession)
    {
	return HXR_OK;
    }

    /*
     * Restart the internal buffer timers
     */

    m_pMutex->Lock();

    SendMsgToTransport(RESUME_BUFFER);

    /*
     * Man, iptv, teracast, and darwin server don't like this even though
     * this is perfetly legal...
     */
    if (m_bNonRSRTP && m_bPlayJustSent)
    {
	m_pResp->HandlePlayResponse(HXR_OK);
	m_pMutex->Unlock();
	return HXR_OK;
    }

    HX_RESULT rc = SendMsgToServer(RTSP_PLAY);

    m_pMutex->Unlock();
    return rc;
}

STDMETHODIMP
RTSPClientProtocol::SendTeardownRequest()
{
    // make sure not to send a TEARDOWN unless SETUP succeeded
    if (m_setupResponseCount <= 0 || !m_pSession)
    {
	// no successful SETUP response received...
	return HXR_OK;
    }

    // it's ok if there is no session by spec.
    m_pMutex->Lock();
    HX_RESULT rc = SendMsgToServer(RTSP_TEARDOWN);
    m_pMutex->Unlock();
    return rc;
}

STDMETHODIMP
RTSPClientProtocol::SendPlayerStats(const char* pStats)
{
#if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
    if (!m_pIsMethodSupported[SET_PARAM])
    {
	return HXR_OK;
    }

    if(m_pSession && !m_sessionID.IsEmpty())
    {
	HX_RESULT rc = HXR_OK;
	m_pMutex->Lock();
	RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
        if(pMsg)
        {
	    pMsg->setURL(m_url);
	    pMsg->addHeader("Session", m_sessionID);
	    pMsg->addHeader("PlayerStats", pStats);
	    UINT32 seqNo = m_pSession->getNextSeqNo(this);
	    rc = sendRequest(pMsg, seqNo);
        }
        else
        {
            rc = HXR_OUTOFMEMORY;
        }
	m_pMutex->Unlock();
	return rc;
    }
#endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */

    return HXR_OK;
}

STDMETHODIMP
RTSPClientProtocol::SendKeepAlive()
{
    HX_RESULT rc = HXR_OK;

    // XXXSMP - Not right! :-)
    m_pMutex->Lock();

    if (!m_pSession)
    {
	// just say alive!
	m_pMutex->Unlock();
	return HXR_OK;
    }

    // Handle server timeout
    if (!m_bKeepLiveResponsed)
    {
        m_pResp->HandleOptionsResponse(HXR_SERVER_TIMEOUT, NULL);
        m_pMutex->Unlock();

        return rc;
    }

    m_bKeepLiveResponsed = FALSE;

    // If using session timeout code, send an Options message,
    // otherwise, send a SetParam.  The SetParam approach is
    // is for servers that do not specify a session timeout value.
    if (!m_bUseLegacyTimeOutMsg ||
        !m_pIsMethodSupported[SET_PARAM] ||
        m_bNoKeepAlive)
    {
        m_bKeepAlivePending = TRUE;
        rc = SendMsgToServer(RTSP_OPTIONS);
    }
    else
    {
        RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
        if(pMsg)
        {
            pMsg->setURL("*");
            MIMEHeader* pAlertHeader = new MIMEHeader("Ping");
            if(pAlertHeader)
            {
                pAlertHeader->addHeaderValue("Pong");
                pMsg->addHeader(pAlertHeader);

                AddCommonHeaderToMsg(pMsg);

                UINT32 seqNo = m_pSession->getNextSeqNo(this);
                sendRequest(pMsg, seqNo);
            }
            else
            {
                rc = HXR_OUTOFMEMORY;
            }
        }
        else
        {
            rc = HXR_OUTOFMEMORY;
        }
    }

    m_pMutex->Unlock();
    return rc;
}

STDMETHODIMP
RTSPClientProtocol::SendPacket(BasePacket* pPacket)
{
    m_pMutex->Lock();
    HX_RESULT rc = HXR_UNEXPECTED;
    RTSPTransport* pTrans =
	(RTSPTransport*)(*m_pTransportStreamMap)[pPacket->GetStreamNumber()];
    if(pTrans)
    {
	rc = pTrans->sendPacket(pPacket);
    }
    m_pMutex->Unlock();
    return rc;
}

STDMETHODIMP
RTSPClientProtocol::SendStreamDone(UINT16 streamNumber)
{
    m_pMutex->Lock();
    HX_RESULT rc = HXR_UNEXPECTED;
    RTSPTransport* pTrans =
	(RTSPTransport*)(*m_pTransportStreamMap)[streamNumber];
    if(pTrans)
    {
	rc = pTrans->streamDone(streamNumber);
    }
    m_pMutex->Unlock();
    return rc;
}

STDMETHODIMP
RTSPClientProtocol::GetPacket(UINT16 uStreamNumber, REF(IHXPacket*) pPacket)
{
    m_pMutex->Lock();

    /*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -