📄 hxntsrc.cpp
字号:
}
delete this;
return 0;
}
HX_RESULT
HXNetSource::Setup(const char* host,
const char* resource,
UINT16 port,
BOOL LossCorrection,
const CHXURL* pURL,
BOOL bAltURL)
{
HX_TRACE("HXNetSource::Setup");
HX_RESULT theErr = HXR_OK;
IHXValues* pValues = NULL;
IHXValues* pRequestHeaders = NULL;
IHXBuffer* pBuffer = NULL;
IHXBuffer* pPlayerCookies = NULL;
if (!m_bBruteForceReconnected &&
!m_bReSetup)
{
theErr = SetupRegistry();
if (HXR_OK != theErr)
{
goto cleanup;
}
}
if (!m_bReSetup)
{
m_ulOriginalDelay = m_ulDelay;
}
// Remember whether or not we ask for loss correction!
m_bLossCorrection = LossCorrection;
// delete protocol object if one exists
HX_RELEASE (m_pProto);
m_uProtocolType = pURL->GetProtocol();
if (rtspProtocol == m_uProtocolType || helixSDPProtocol == m_uProtocolType)
{
m_bRTSPProtocol = TRUE;
m_ulSendStatsMask = MAX_STATS_MASK;
/* Perfect Play Always supported iin RTSP,
* till we add some preference to disable it.
*/
BOOL bSupported = TRUE;
SetOption(HX_PERFECTPLAY_SUPPORTED, &bSupported);
}
if (helixSDPProtocol != m_uProtocolType)
{
// get out immediately if we have bogus parameters
if(!host || !*host)
{
theErr = HXR_INVALID_URL_HOST;
goto cleanup;
}
if(!theErr && (!resource || !*resource))
{
theErr = HXR_INVALID_URL_PATH;
goto cleanup;
}
if (m_pHost != host)
{
HX_VECTOR_DELETE(m_pHost);
m_pHost = new char[::strlen(host) + 1];
if (!m_pHost)
{
theErr = HXR_OUTOFMEMORY;
goto cleanup;
}
::strcpy(m_pHost, host); /* Flawfinder: ignore */
}
if(m_pResource != resource)
{
HX_VECTOR_DELETE(m_pResource);
m_pResource = new char[::strlen(resource) + 1];
if (!m_pResource)
{
theErr = HXR_OUTOFMEMORY;
goto cleanup;
}
::strcpy(m_pResource, resource); /* Flawfinder: ignore */
}
}
// save parameters for use with different protocols.
#if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
// save URL to the registry
if (m_pStats)
{
m_pStats->m_pSourceName->SetStr((char*)pURL);
}
#endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
if (m_pURL != pURL)
{
HX_DELETE(m_pURL);
m_pURL = new CHXURL(*pURL);
if (!m_pURL)
{
theErr = HXR_OUTOFMEMORY;
goto cleanup;
}
HX_VECTOR_DELETE(m_pszURL);
m_pszURL = new char[::strlen(m_pURL->GetURL()) + 1];
if (!m_pszURL)
{
theErr = HXR_OUTOFMEMORY;
goto cleanup;
}
::strcpy(m_pszURL, m_pURL->GetURL()); /* Flawfinder: ignore */
}
m_uPort = port;
HX_VECTOR_DELETE(m_pPath);
pValues = m_pURL->GetProperties();
if (pValues &&
HXR_OK == pValues->GetPropertyBuffer(PROPERTY_PATH, pBuffer) && pBuffer)
{
StrAllocCopy(m_pPath, (char*)pBuffer->GetBuffer());
}
HX_RELEASE(pBuffer);
HX_RELEASE(pValues);
// set request
m_bAltURL = bAltURL;
SetRequest(m_pURL, bAltURL);
if (!m_pCookies && HXR_OK != m_pEngine->QueryInterface(IID_IHXCookies, (void**)&m_pCookies))
{
m_pCookies = NULL;
}
if (!m_pCookies2 && HXR_OK != m_pEngine->QueryInterface(IID_IHXCookies2, (void**)&m_pCookies2))
{
m_pCookies2 = NULL;
}
if (m_pCookies || m_pCookies2)
{
if (HXR_OK == m_pRequest->GetRequestHeaders(pRequestHeaders) && pRequestHeaders)
{
HX_RESULT res = HXR_FAIL;
if(m_pCookies2)
res = m_pCookies2->GetCookies(m_pHost, m_pPath, pBuffer, pPlayerCookies);
else if(m_pCookies)
res = m_pCookies->GetCookies(m_pHost, m_pPath, pBuffer);
if (HXR_OK == res && pBuffer)
{
pRequestHeaders->SetPropertyCString("Cookie", pBuffer);
if(pPlayerCookies)
{
pRequestHeaders->SetPropertyCString("PlayerCookie", pPlayerCookies);
}
}
HX_RELEASE(pBuffer);
HX_RELEASE(pPlayerCookies);
}
}
HX_RELEASE(pRequestHeaders);
#if defined(HELIX_FEATURE_SMARTERNETWORK)
if (!m_pPreferredTransportManager &&
HXR_OK != m_pEngine->QueryInterface(IID_IHXPreferredTransportManager,
(void**)&m_pPreferredTransportManager))
{
theErr = HXR_FAILED;
goto cleanup;
}
#endif /* HELIX_FEATURE_SMARTERNETWORK */
// Read all relevant preferences...
theErr = ReadPreferences();
// either we will wait for the first source to negotiate the transport
// then connect the remaining sources
// or we are initiating PAC(ProxyAutoConfig)
if (HXR_WOULD_BLOCK == theErr)
{
theErr = HXR_OK;
}
else if (HXR_OK == theErr)
{
theErr = FinishSetup();
}
cleanup:
return theErr;
}
HX_RESULT
HXNetSource::FinishSetup()
{
HX_RESULT rc = HXR_OK;
BOOL bSDPInitiated = FALSE;
CHXString pString;
// start off with the preferred protocol
rc = CreateProtocol();
if (HXR_OK != rc)
{
goto cleanup;
}
rc = InitializeProtocol();
if (HXR_OK != rc)
{
goto cleanup;
}
if (helixSDPProtocol == m_uProtocolType)
{
bSDPInitiated = TRUE;
CHXURL::decodeURL(m_pURL->GetEscapedURL(), pString);
HX_VECTOR_DELETE(m_pResource);
m_pResource = new char[pString.GetLength() - 9];
::strcpy(m_pResource, (const char*)pString + 10);
}
rc = m_pProto->setup(m_pHost,
m_pResource,
m_uPort,
m_bLossCorrection,
(HTTPCloakMode == m_CurrentTransport)?TRUE:FALSE,
bSDPInitiated,
m_uCurrCloakedPort);
// Mask this error
// Let the _ProcessIdle() determine whether ReportError() or
// TransportSwitching for HXR_BAD_TRANSPORT
if(rc == HXR_BLOCK_CANCELED || rc == HXR_BAD_TRANSPORT)
{
rc = HXR_OK;
}
if (HXR_OK != rc)
{
mLastError = rc;
goto cleanup;
}
// create log info list
m_pLogInfoList = new CHXSimpleList;
m_ulLogInfoLength = 0;
// start time of this source
m_ulSourceStartTime = HX_GET_TICKCOUNT();
if (m_pBufferCtl)
{
m_pBufferCtl->Close();
}
HX_RELEASE(m_pBufferCtl);
HX_RELEASE(m_pWMBufferCtl);
#ifdef HELIX_FEATURE_FEEDBACK_BUFFER_CONTROL
m_pBufferCtl = new HXFeedbackBufferControl();
#else
m_pBufferCtl = new HXWatermarkBufferControl();
#endif /* HELIX_FEATURE_FEEDBACK_BUFFER_CONTROL */
if (m_pBufferCtl)
{
m_pBufferCtl->AddRef();
m_pBufferCtl->QueryInterface(IID_IHXWatermarkBufferControl,
(void**)&m_pWMBufferCtl);
m_pBufferCtl->Init((IUnknown*)(IHXStreamSource*)this);
if (m_pWMBufferCtl)
{
m_pWMBufferCtl->SetSource(this);
}
}
cleanup:
if (HXR_OK != rc)
{
HX_RELEASE(m_pProto);
}
return rc;
}
HX_RESULT
HXNetSource::DoSeek(ULONG32 seekTime)
{
HX_TRACE("HXNetSource::DoSeek");
BOOL bSeekInsideRecordControl = FALSE;
if ((!m_pProto && m_state != NETSRC_RECONNECTPENDING) ||
(mLiveStream && !m_bPlayFromRecordControl && m_bSourceEnd))
{
return HXR_OK;
}
// log seek action
LogInformation("SEEK", NULL);
if (seekTime >= m_ulDelay)
{
seekTime -= m_ulDelay;
m_bDelayed = FALSE;
}
else
{
seekTime = 0;
/* This source has not been even started yet...
* Do not attempt to seek it if the start time = 0
*/
if (m_bDelayed && m_ulStartTime == 0 && !m_bSourceEnd)
{
// will start pre-fetch again in TryResume()
if (!m_bIsPreBufferingDone)
{
m_bIsPreBufferingStarted = FALSE;
// will be registered again in DoResume() or TryResume()
if (m_pSourceInfo)
{
m_pSourceInfo->UnRegister();
}
}
return HXR_OK;
}
m_bDelayed = TRUE;
}
/* Add any start time to seek time */
seekTime += m_ulStartTime;
/* Are we seeking past the last expected packet time?
* If so, don't bother... and mark this source as done
*/
HX_ASSERT(m_llLastExpectedPacketTime <= MAX_UINT32);
// XXX HP make sure the source has been initialized otherwise
// m_llLastExpectedPacketTime could be 0 and we could falsely
// mark the source ended
if (m_bInitialized && !mLiveStream && seekTime >= m_llLastExpectedPacketTime)
{
if (m_pSourceInfo && m_pSourceInfo->m_bSeekToLastFrame)
{
seekTime = INT64_TO_ULONG32(m_llLastExpectedPacketTime);
}
else
{
m_bSourceEnd = TRUE;
m_bForcedSourceEnd = TRUE;
AdjustClipBandwidthStats(FALSE);
#if defined(HELIX_FEATURE_RECORDCONTROL)
if (m_pRecordControl)
{
m_pRecordControl->Seek(seekTime);
}
#endif /* HELIX_FEATURE_RECORDCONTROL*/
goto cleanup;
}
}
// workaround for b#42118 for older servers(<= RealServer8.0 Gold)
// server sends no more streamdone when reaching the endtime if seek
// is occurred after streamdone has been sent. fix has been made in the latest server
if (m_bSourceEnd && m_bCustomEndTime && m_pProto && m_pProto->GetRDTFeatureLevel() < 2)
{
m_bRTSPRuleFlagWorkAround = TRUE;
}
if (mLiveStream)
{
seekTime += m_ulFirstPacketTime;
}
#if defined(HELIX_FEATURE_RECORDCONTROL)
if (m_pRecordControl && m_pRecordControl->Seek(seekTime) == HXR_OK &&
m_bPlayFromRecordControl)
{
bSeekInsideRecordControl = TRUE;
}
else
#endif /* HELIX_FEATURE_RECORDCONTROL */
{
m_ulSeekPendingTime = seekTime;
m_bSeekPending = TRUE;
if(m_pProto)
m_pProto->seek(seekTime, seekTime, FALSE);
if (mLiveStream)
{
seekTime = 0;
}
m_bSourceEnd = FALSE;
m_bForcedSourceEnd = FALSE;
STREAM_INFO* pStreamInfo = NULL;
CHXMapLongToObj::Iterator lStreamIterator = mStreamInfoTable->Begin();
for (; lStreamIterator != mStreamInfoTable->End(); ++lStreamIterator)
{
pStreamInfo = (STREAM_INFO*) (*lStreamIterator);
pStreamInfo->ResetPreReconnectEventList();
}
}
// initiating reconnect NOW ...
if (NETSRC_RECONNECTPENDING == m_state)
{
m_state = NETSRC_RECONNECTFORCED;
if (m_pReconnectCallback)
{
m_pReconnectCallback->CancelCallback();
}
StartReconnect();
}
m_uLastBuffering = 0;
m_bInitialBuffering = TRUE;
m_bIsPreBufferingStarted = FALSE;
m_bIsPreBufferingDone = FALSE;
m_pushDownStatus = PUSHDOWN_NONE;
if (m_pBufferCtl)
{
m_pBufferCtl->OnSeek();
}
// Buffer manager needs to know whether we seek inside the RecordControl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -