📄 rtspclnt.cpp
字号:
} pPluginEnumerator->Release(); } } HX_RELEASE(pPluginGroupEnum); pMsg->addHeader("Accept", (const char*)mimeTypes); AddCommonHeaderToMsg(pMsg); addRFC822Headers(pMsg, pValuesRequestHeaders); appendAuthorizationHeaders(pMsg); HX_RELEASE(pValuesRequestHeaders); UINT32 seqNo = m_pSession->getNextSeqNo(this); rc = sendRequest(pMsg, seqNo); m_pMutex->Unlock(); return rc;}STDMETHODIMPRTSPClientProtocol::SendStreamRecordDescriptionRequest( const char* pURL, IHXValues* pFileHeader, CHXSimpleList* pStreams, IHXValues* pRequestHeaders){ HX_RESULT rc = HXR_OK; IHXBuffer* pDescription = 0; if (!m_pIsMethodSupported[ANNOUNCE]) { return HXR_OK; } // Let's make sure we have enough mem before we do the mutex lock. RTSPAnnounceMessage* pMsg = new RTSPAnnounceMessage; if(!pMsg) { return HXR_OUTOFMEMORY; } m_pMutex->Lock(); pMsg->setURL(pURL); m_url = pURL; const char* pDesc = 0; addRFC822Headers(pMsg, pRequestHeaders); clearStreamInfoList(); // use the first stream description plugin found... char* pMimeType = 0; if(HXR_OK == getStreamDescriptionMimeType(pMimeType)) { IHXStreamDescription* pSD = getStreamDescriptionInstance(pMimeType); if(pSD) { UINT32 streamNumber; UINT32 needReliable; UINT32 rtpPayloadType; UINT32 ulIsLive; IHXBuffer* pControlString; UINT32 ulIsSessionLive = 0; // if we are talking to a realserver, we will make an old sdpfile // for now...We need to check version and send the spec complient // sdp! IHXValues* pResponseHeaders = NULL; if (HXR_OK == m_pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseHeaders)) { pFileHeader->SetPropertyULONG32("SdpFileType", GetSdpFileTypeWeNeed(pResponseHeaders)); } HX_RELEASE(pResponseHeaders); UINT16 nStreams = pStreams->GetCount(); IHXValues** ppValues = new IHXValues*[nStreams+2]; if(!ppValues) { rc = HXR_OUTOFMEMORY; HX_DELETE(pMsg); goto overandout; } ppValues[0] = pFileHeader; ppValues[1] = 0; // no options pFileHeader->GetPropertyULONG32("LiveStream", ulIsSessionLive); CHXSimpleList::Iterator i; INT16 j=2; for(i=pStreams->Begin();i!=pStreams->End();++i,++j) { // reset... streamNumber = 0; needReliable = 0; rtpPayloadType = (UINT32)-1; ulIsLive = ulIsSessionLive; pControlString = 0; ppValues[j] = (IHXValues*)(*i); // build stream info list RTSPStreamInfo* pInfo = new RTSPStreamInfo; if(!pInfo) { rc = HXR_OUTOFMEMORY; HX_DELETE(pMsg); HX_VECTOR_DELETE(ppValues); goto overandout; } ppValues[j]->GetPropertyULONG32("StreamNumber", streamNumber); ppValues[j]->GetPropertyULONG32("NeedReliablePackets", needReliable); ppValues[j]->GetPropertyULONG32("RTPPayloadType", rtpPayloadType); ppValues[j]->GetPropertyCString("Control", pControlString); ppValues[j]->GetPropertyULONG32("LiveStream", ulIsLive); pInfo->m_streamNumber = (UINT16)streamNumber; pInfo->m_bNeedReliablePackets = needReliable? TRUE: FALSE; pInfo->m_rtpPayloadType = (INT16)rtpPayloadType; pInfo->m_bIsLive = ulIsLive ? TRUE : FALSE; pInfo->m_sPort = 0; if(pControlString) { pInfo->m_streamControl = pControlString->GetBuffer(); // done with the buffer pControlString->Release(); pControlString = NULL; } else { char tmp[32]; SafeSprintf(tmp,32, "streamid=%u", (UINT16)streamNumber); pInfo->m_streamControl = tmp; } m_streamInfoList.AddTail(pInfo); } pSD->GetDescription(nStreams+2, ppValues, pDescription); pDesc = (const char*)pDescription->GetBuffer(); pSD->Release(); delete[] ppValues; } } if(pDesc) { m_bSetupRecord = TRUE;#ifdef _MACINTOSH// someday, someone in core should look at why m_pSession is NULL when// an invalid port is used, and yet m_pSession is assumed to be valid, and subsequently// crashes macs HARD. I would attempt to investigate this further, however// the core deferred task keeps crashing the debugger while I am attempting// to trace through why m_pSession never gets assigned. since Mac Producer goes// beta in 2 weeks, I'm putting this 'fix' in here now.. rlovejoy 2/16/00 if (m_pSession == NULL) { rc = HXR_PORT_IN_USE; } else#endif { UINT32 seqNo = m_pSession->getNextSeqNo(this); rc = sendRequest(pMsg, pDesc, pMimeType, seqNo); } // done with the description, we need to clean it up pDescription->Release(); } else { rc = HXR_FAIL; }overandout: delete[] pMimeType; m_pMutex->Unlock(); return rc;}STDMETHODIMPRTSPClientProtocol::SendSetupRequest( RTSPTransportType* pTransType, UINT16 nTransTypes, IHXValues* pIHXValuesRequestHeaders){ m_pMutex->Lock(); HX_RESULT rc = HXR_OK; IHXUDPSocket* pUDPSocket = NULL; IHXUDPSocket* pRTCPUDPSocket = NULL; RTSPTransport* pTrans = NULL; RTCPUDPTransport* pRTCPTrans = NULL; RTSPStreamInfo* pStreamInfo = NULL; IHXSetSocketOption* pSockOpt = NULL; CHXSimpleList::Iterator i;#if defined(HELIX_FEATURE_TRANSPORT_MULTICAST) if (m_bSDPInitiated && m_bMulticast) { RTSPTransportRequest* pRequest = new RTSPTransportRequest(RTSP_TR_RTP_MCAST, 0); if(pRequest) { m_transportRequestList.AddTail(pRequest); } else { rc = HXR_OUTOFMEMORY; goto cleanup; } for (i=m_streamInfoList.Begin();i!=m_streamInfoList.End();++i) { pStreamInfo = (RTSPStreamInfo*)(*i); pUDPSocket = (IHXUDPSocket*)(*m_pUDPSocketStreamMap)[pStreamInfo->m_streamNumber]; pRTCPUDPSocket = (IHXUDPSocket*)(*m_pRTCPSocketStreamMap)[pStreamInfo->m_streamNumber]; // create a new transport for each setup pTrans = new RTPUDPTransport(m_bSetupRecord); if(!pTrans) { rc = HXR_OUTOFMEMORY; goto cleanup; } pTrans->AddRef(); if (HXR_OK != ((RTPUDPTransport*)pTrans)->init(m_pContext, pUDPSocket, (IHXRTSPTransportResponse*)this)) { rc = HXR_BAD_TRANSPORT; goto cleanup; } pTrans->notifyEmptyRTPInfo(); // create an RTCP transport for this stream pRTCPTrans = new RTCPUDPTransport(m_bSetupRecord); if (!pRTCPTrans) { rc = HXR_OUTOFMEMORY; goto cleanup; } pRTCPTrans->AddRef(); if (HXR_OK != pRTCPTrans->init(m_pContext, pRTCPUDPSocket, (RTPUDPTransport*)pTrans, (IHXRTSPTransportResponse*) this, pStreamInfo->m_streamNumber)) { rc = HXR_BAD_TRANSPORT; goto cleanup; } pRTCPTrans->notifyEmptyRTPInfo(); ((RTPUDPTransport*)pTrans)->setRTCPTransport(pRTCPTrans); pTrans->addStreamInfo(pStreamInfo); (*m_pTransportStreamMap)[pStreamInfo->m_streamNumber] = pTrans; (*m_pTransportMPortMap)[pStreamInfo->m_sPort] = pTrans; pTrans->JoinMulticast(m_ulConnectToAddr, pStreamInfo->m_sPort, pUDPSocket); (*m_pTransportMPortMap)[pStreamInfo->m_sPort+1] = pRTCPTrans; pRTCPTrans->JoinMulticast(m_ulConnectToAddr, pStreamInfo->m_sPort + 1, pRTCPUDPSocket); if ((!m_bHasSyncMasterStream) && (pStreamInfo->m_eMediaType == RTSPMEDIA_TYPE_AUDIO)) { pStreamInfo->m_bIsSyncMaster = TRUE; m_bHasSyncMasterStream = TRUE; } mapControlToStreamNo(pStreamInfo->m_streamControl, pStreamInfo->m_streamNumber); rc = pRequest->addTransportInfo(pTrans, (RTCPBaseTransport*)pRTCPTrans, pStreamInfo->m_streamNumber, 0); if( rc == HXR_OUTOFMEMORY ) { goto cleanup; } rc = pUDPSocket->Read(HX_SAFEUINT(MAX_UDP_PACKET)); if( rc == HXR_OUTOFMEMORY ) { goto cleanup; } rc = pRTCPUDPSocket->Read(HX_SAFEUINT(MAX_UDP_PACKET)); if( rc == HXR_OUTOFMEMORY ) { goto cleanup; } } m_uProtocolType = 1; m_pResp->HandleSetupResponse(HXR_OK); goto cleanup; }#endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */ if( HXR_OUTOFMEMORY == extractExistingAuthorizationInformation(pIHXValuesRequestHeaders)) { rc = HXR_OUTOFMEMORY; goto cleanup; } if(pTransType) { for(int i=0;i<nTransTypes;++i) { RTSPTransportRequest* pRequest = new RTSPTransportRequest(pTransType[i].m_lTransportType, pTransType[i].m_sPort); if(pRequest) { m_transportRequestList.AddTail(pRequest); } else { rc = HXR_OUTOFMEMORY; break; } } } if (m_bIPTV && rc == HXR_OK) { // we are going to keep this around for now to send cookie in all SETUP. m_pSetupRequestHeader = pIHXValuesRequestHeaders; m_pSetupRequestHeader->AddRef(); } if (rc == HXR_OK) { rc = sendFirstSetupRequest(pIHXValuesRequestHeaders); }cleanup: if (HXR_OK != rc) { HX_RELEASE(pRTCPTrans); HX_RELEASE(pTrans); } m_pMutex->Unlock(); return rc;}HX_RESULTRTSPClientProtocol::sendFirstSetupRequest( IHXValues* pIHXValuesRequestHeaders){ m_setupResponseCount = 0; if (!m_streamInfoList.IsEmpty()) { RTSPStreamInfo* pStreamInfo = (RTSPStreamInfo*)m_streamInfoList.GetHead(); if(pStreamInfo) { return sendSetupRequestMessage ( pStreamInfo, pIHXValuesRequestHeaders, TRUE ); } } return HXR_FAIL;}HX_RESULTRTSPClientProtocol::sendRemainingSetupRequests(){ HX_RESULT status = HXR_OK; CHXSimpleList::Iterator i; BOOL bFirst = TRUE; for(i=m_streamInfoList.Begin(); status == HXR_OK && (i!=m_streamInfoList.End());++i) { if(bFirst) { bFirst = FALSE; } else { RTSPStreamInfo* pStreamInfo = (RTSPStreamInfo*)(*i); status = sendSetupRequestMessage(pStreamInfo, NULL, FALSE); } } return status;}HX_RESULTRTSPClientProtocol::sendSetupRequestMessage(RTSPStreamInfo* pStreamInfo, IHXValues* pIHXValuesRequestHeaders, BOOL bFirstSetup){ m_pMutex->Lock(); RTSPSetupMessage* pMsg = new RTSPSetupMessage; if(!pMsg) { m_pMutex->Unlock(); return HXR_OUTOFMEMORY; } HX_RESULT status = HXR_OK; status = sendSetupRequestMessageExt(pStreamInfo, pIHXValuesRequestHeaders, bFirstSetup, pMsg); pMsg->addHeader("User-Agent", m_versionString); if (bFirstSetup && !m_sessionID.IsEmpty()) { pMsg->addHeader("If-Match", m_sessionID); } else if (!m_sessionID.IsEmpty()) { pMsg->addHeader("Session", m_sessionID); } // append stream control string to request setSetupRequestURL(pMsg, pStreamInfo); if (pIHXValuesRequestHeaders) { addUAProfHeaders(pIHXValuesRequestHeaders); addRFC822Headers(pMsg, pIHXValuesRequestHeaders); } UINT32 seqNo; seqNo = m_pSession->getNextSeqNo(this); /* Why are we not checking for any error code from above ??? */ status = sendRequest(pMsg, seqNo); m_pMutex->Unlock(); return status;}HX_RESULTRTSPClientProtocol::sendSetupRequestMessageExt(RTSPStreamInfo* pStreamInfo, IHXValues*& pIHXValuesRequestHeaders, BOOL bFirstSetup, RTSPSetupMessage*& pMsg){ MIMEHeader* pHeader = new MIMEHeader("Transport"); if(!pHeader) { return HXR_OUTOFMEMORY; } HX_RESULT status = HXR_OK; CHXSimpleList::Iterator i; for(i=m_transportRequestList.Begin();i!=m_transportRequestList.End();++i) { RTSPTransportRequest* pRequest = (RTSPTransportRequest*)(*i); UINT16 streamNumber = pStreamInfo->m_streamNumber; UINT16 nUDPPort = 0;#if defined(HELIX_FEATURE_RTP) switch(pRequest->m_lTransportType) { case RTSP_TR_RTP_UDP: { // create a new transport for each setup RTSPTransport* pTrans = new RTPUDPTransport(m_bSetupRecord); if(!pTrans) { HX_DELETE(pHeader); return HXR_OUTOFMEMORY; } pTrans->AddRef(); if (m_bPrefetch) { pTrans->EnterPrefetch(); } IHXUDPSocket* pUDPSocket = (IHXUDPSocket*) (*m_pUDPSocketStreamMap)[streamNumber]; pUDPSocket->GetLocalPort(nUDPPort); IHXUDPSocket* pRTCPSocket = (IHXUDPSocket*) (*m_pRTCPSocketStreamMap)[streamNumber]; if (HXR_OK != ((RTPUDPTransport*)pTrans)->init( m_pContext, pUDPSocket, (IHXRTSPTransportResponse*) this)) { pTrans->Release(); return HXR_BAD_TRANSPORT; } // 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -