📄 rtspclnt.cpp
字号:
IHXPluginEnumerator* pPluginEnumerator = NULL;
m_pContext->QueryInterface
(
IID_IHXPluginEnumerator,
(void**)&pPluginEnumerator
);
if(pPluginEnumerator)
{
IUnknown* pUnknown = NULL;
ULONG32 ulNumPlugins = pPluginEnumerator->GetNumOfPlugins();
for(ULONG32 i=0;i<ulNumPlugins;++i)
{
if(SUCCEEDED(pPluginEnumerator->GetPlugin(i, pUnknown)))
{
GetStreamDescriptionInfo(pUnknown, mimeTypes);
HX_RELEASE(pUnknown);
}
}
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;
}
STDMETHODIMP
RTSPClientProtocol::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;
}
STDMETHODIMP
RTSPClientProtocol::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_RESULT
RTSPClientProtocol::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_RESULT
RTSPClientProtocol::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_RESULT
RTSPClientProtocol::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_RESULT
RTSPClientProtocol::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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -