📄 hxsm.cpp
字号:
UINT32 ulLowestBandwidthBeforeTimeStamp = 0;
if (pInfo->m_ulFixedBandwidth != 0)
{
ulLowestBandwidthBeforeTimeStamp = pInfo->m_ulFixedBandwidth;
}
else
{
// XXXNH: 6/7/99
// We make this threshold array once and create it to be as large
// as we will ever possibly need. Each subsequent call to
// GetThresholdInfo() should never need more than GetNumThresholds
// returns. UNLESS the ASMStreamInfo's m_pNegotiator were to
// change, but I don't think that's a feature we support.
UINT32 ulNumThresholds =
pInfo->m_pNegotiator->GetNumThresholds();
pInfo->m_pThreshold = new float[ulNumThresholds];
pInfo->m_pNegotiator->GetThresholdInfo(
(float*)pInfo->m_pThreshold,
pInfo->m_ulNumThresholds);
pInfo->m_ulMaxEffectiveThreshold = pInfo->m_ulNumThresholds - 1;
ulNumThresholds = pInfo->m_ulNumThresholds;
ulLowestBandwidthBeforeTimeStamp = (UINT32) pInfo->m_pThreshold[ulNumThresholds-1];
for (UINT32 i = ulNumThresholds-1; i > 0 ; i--)
{
UINT32 ulCurBand = (UINT32) pInfo->m_pThreshold[i];
// used for timestamp rules
if (ulCurBand == 0 || ulCurBand == 1)
{
break;
}
else
{
ulLowestBandwidthBeforeTimeStamp = ulCurBand;
}
}
}
HX_ASSERT(ulLowestBandwidthBeforeTimeStamp != 0);
pASMSourceInfo->m_ulLowestBandwidthBeforeTimeStamp += ulLowestBandwidthBeforeTimeStamp;
HX_RELEASE(pStream);
}
// Rule for determining if SetDeliveryBandwidth is used.
//
// HXASMStream::bFixed bEnabledSDB m_bEnableSDB
// ------------------------------------------
// FALSE FALSE TRUE // no fbw means bw > 1
// FALSE TRUE TRUE // at least one rule is fbw==1
// TRUE FALSE FALSE // all bw are fbw==1
// TRUE TRUE TRUE // no streamcount, SDB true
m_bEnableSDB = bEnableSDB;
return HXR_OK;
}
STDMETHODIMP
HXSM::RegisterSourcesDone()
{
if (m_pASMSourceInfo->GetCount() > 0 &&
m_pASMStreamInfo->GetCount() > 0)
{
CHXSimpleList::Iterator i;
ASMSourceInfo* pASMSourceInfo;
for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
{
pASMSourceInfo = (ASMSourceInfo*)(*i);
if (pASMSourceInfo && pASMSourceInfo->m_pSource)
{
DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s, "(%p)RegisterSourcesDone AccelFactor:%f", pASMSourceInfo->m_pSource, m_fAccelerationFactor));
if (pASMSourceInfo->m_pSource->m_bFastStart)
{
pASMSourceInfo->m_ulLastSetDelivery = 0;
}
}
}
m_State = INIT;
RecalcAccel();
}
return HXR_OK;
}
BOOL
HXSM::NotEnoughBandwidth()
{
CHXSimpleList::Iterator i;
ASMSourceInfo* pASMSourceInfo;
UINT32 ulTotal = 0;
BOOL bIsLive = FALSE;
for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
{
pASMSourceInfo = (ASMSourceInfo*)(*i);
ulTotal += pASMSourceInfo->m_ulSubscribedBw;
if (pASMSourceInfo->m_pSource &&
pASMSourceInfo->m_pSource->IsLive())
{
bIsLive = TRUE;
}
}
if (bIsLive && ulTotal > m_ulHighestBandwidthAvail)
{
return TRUE;
}
else
{
return FALSE;
}
}
STDMETHODIMP
HXSM::UnRegisterSource(HXSource* pSource)
{
LISTPOSITION lPos;
ASMSourceInfo* pASMSourceInfo = 0;
ASMStreamInfo* pASMStreamInfo;
BOOL bFound = FALSE;
lPos = m_pASMSourceInfo->GetHeadPosition();
DEBUG_OUT(m_pEM, DOL_BWMGR, (s, "UnRegister Source %p %s", pSource, pSource->GetURL()));
while (lPos)
{
pASMSourceInfo = (ASMSourceInfo *)m_pASMSourceInfo->GetAt(lPos);
if (pASMSourceInfo->m_pSource == pSource)
{
m_pASMSourceInfo->RemoveAt(lPos);
pASMSourceInfo->Done();
bFound = TRUE;
break;
}
m_pASMSourceInfo->GetNext(lPos);
}
if (!bFound)
{
return HXR_OK;
}
lPos = m_pASMStreamInfo->GetHeadPosition();
while (lPos)
{
pASMStreamInfo = (ASMStreamInfo*) m_pASMStreamInfo->GetAt(lPos);
if (pASMStreamInfo->m_pASMSourceInfo == pASMSourceInfo)
{
/* RemoveAt returns the next position in the list.
* DO NOT use GetNext if you remove a node.
*/
lPos = m_pASMStreamInfo->RemoveAt(lPos);
if (pASMStreamInfo->m_pNegotiator)
{
pASMStreamInfo->m_pNegotiator->UnRegister();
}
delete pASMStreamInfo;
}
else
{
m_pASMStreamInfo->GetNext(lPos);
}
}
HX_RELEASE(pASMSourceInfo);
m_ulNumSources--;
if (m_ulNumSources > 0)
{
m_State = REDIST;
RecalcAccel();
}
return HXR_OK;
}
/* Called by HXPlayer at end of each presentation */
STDMETHODIMP
HXSM::PresentationDone(void)
{
if (m_ulNumSources == 0)
{
m_ulHighestBandwidthAvail = 0;
m_ulPeakUsedBandwidth = 0;
m_bInitialHighBwAvail = TRUE;
m_bPipeFull = FALSE;
m_bUpShiftInfoReady = FALSE;
m_ulUpShiftRingPos = 0;
m_ulUpShiftBandwidthAvail = 0;
m_ulNumReportsSinceUpShift = 2;
m_ulOfferToRecalc = 0;
m_State = HX_NONE;
m_bDidOfferUpShiftToRecalc = FALSE;
m_lLoss = 0;
m_ulNextPacketWindow = 0;
m_lPacketCounter = 0;
m_ulUpShiftPastResistanceCount = 0;
m_ulUpShiftTestPointScaleFactor = 4000;
}
return HXR_OK;
}
/* If the source has enough data, it may tell the bandwidth
* manager to cut down on accelerated buffering.
*/
STDMETHODIMP
HXSM::ChangeAccelerationStatus(HXSource* pSource,
BOOL bMayBeAccelerated,
BOOL bUseAccelerationFactor,
UINT32 ulAccelerationFactor)
{
LISTPOSITION lPos;
ASMSourceInfo* pASMSourceInfo = 0;
BOOL bFound = FALSE;
lPos = m_pASMSourceInfo->GetHeadPosition();
while (lPos)
{
pASMSourceInfo = (ASMSourceInfo *)m_pASMSourceInfo->GetAt(lPos);
if (pASMSourceInfo->m_pSource == pSource)
{
bFound = TRUE;
break;
}
m_pASMSourceInfo->GetNext(lPos);
}
/* This assert may happen if you are in PNA and are in the debugger
* accumulating tons of data at the networking layer
*/
// HX_ASSERT(bFound);
if (bFound)
{
pASMSourceInfo->ChangeAccelerationStatus(bMayBeAccelerated,
bUseAccelerationFactor, ulAccelerationFactor);
}
else
{
/* Hmmm... ASM cannot help us here */
/* Must be PNA. This may happen in case of TCP where the server sends
* data 300% faster than the content bandwidth.
* Do the old style flow control by Pausing/Resuming the server
*/
if (!bMayBeAccelerated)
{
pSource->DoPause();
}
else
{
pSource->DoResume();
}
}
return HXR_OK;
}
//ChangeBW() allows setting the maximum bandwidth limit on a source. Called by
//RTSPProtocol::HandleSetParameterRequest()
STDMETHODIMP
HXSM::ChangeBW(UINT32 newBW, HXSource* pSource)
{
CHXSimpleList::Iterator ii;
ASMSourceInfo* pASMSourceInfo;
BOOL bSourceFound = FALSE;
DEBUG_OUT(m_pEM, DOL_BWMGR, (s,"(%p)Request to change BW to %ld", pSource, newBW));
for(ii = m_pASMSourceInfo->Begin(); ii != m_pASMSourceInfo->End(); ++ii)
{
pASMSourceInfo = (ASMSourceInfo*)(*ii);
if (pASMSourceInfo->m_pSource == pSource) //Comparing Pointers
{
bSourceFound = TRUE;
ASMRuleBook* pRuleBook = pASMSourceInfo->m_pMasterRuleBook;
BOOL bDownShift = FALSE;
if (pRuleBook)
{
UINT32 ulNumStreamsForThisSource =
pASMSourceInfo->m_pSource->GetStreamCount();
BOOL* pCurrentSubInfo = new BOOL[pRuleBook->GetNumRules()];
HXSMUpdateSubscriptionVars(m_pSubscriptionVariables,
newBW, FALSE, 0);
HX_RESULT lResult =
pRuleBook->GetSubscription(pCurrentSubInfo, m_pSubscriptionVariables);
HX_ASSERT(lResult == HXR_OK);
for (UINT16 idxRule = 0; idxRule < pRuleBook->GetNumRules();
idxRule++)
{
if (pCurrentSubInfo[idxRule])
{
IHXValues* pProps = 0;
// Set Distribution
pRuleBook->GetProperties(idxRule, pProps);
for (UINT32 j = 0; j < ulNumStreamsForThisSource; j++)
{
UINT8 pTemp[128];
IHXBuffer* pBw = NULL;
// Don't assume that streamid == index in pASMSourceInfo->m_pStreams[j]
SafeSprintf((char *)pTemp, 128, "Stream%ldBandwidth", pASMSourceInfo->m_pStreams[j]->m_ulStreamNumber); /* Flawfinder: ignore */
/*
* if this tripps either there's a bug in here or
* the content is messed up
*
*/
HX_VERIFY(HXR_OK==
pProps->GetPropertyCString((char*)pTemp, pBw));
if (pBw)
{
BOOL bFoundMax=FALSE;
UINT32 newMaxBW = (UINT32)
(atoi((char*)pBw->GetBuffer()));
for(int cnt =0;
cnt < (int)pASMSourceInfo->m_pStreams[j]->
m_ulNumThresholds; cnt++)
{
if (newMaxBW ==
pASMSourceInfo->m_pStreams[j]->m_pThreshold[cnt])
{
bFoundMax = TRUE;
pASMSourceInfo->m_pStreams[j]->
m_ulMaxEffectiveThreshold = cnt;
// We are downshifting!!
if ((int)pASMSourceInfo->m_pStreams[j]->
m_ulThresholdPosition > cnt)
{
bDownShift = TRUE;
pASMSourceInfo->m_pStreams[j]->
m_ulThresholdPosition = cnt;
}
// We will try to upshift
else if ((int)pASMSourceInfo->m_pStreams[j]->
m_ulThresholdPosition < cnt)
pASMSourceInfo->m_bTryToUpShift = TRUE;
break;
}
}
HX_ASSERT(bFoundMax);
if (bDownShift || pASMSourceInfo->m_bTryToUpShift)
pASMSourceInfo->m_bAdjustBandwidth = TRUE;
pBw->Release();
pBw = NULL;
}
}
HX_RELEASE(pProps);
}
}
}
//Assume a single stream source, or a fixedbw source ..
//for live, we have more than 1 streams ??
else
{
BOOL bFoundMax = FALSE;
UINT32 numStreams = pASMSourceInfo->m_pSource->GetStreamCount();
//for(int j = 0; j < numStreams; j++)
// {
for(int cnt =0;
cnt < (int)pASMSourceInfo->m_pStreams[0]->m_ulNumThresholds; cnt++)
{
if (newBW == pASMSourceInfo->m_pStreams[0]->m_pThreshold[cnt])
{
bFoundMax = TRUE;
// We are downshifting!!
if ((int)pASMSourceInfo->m_pStreams[0]->m_ulThresholdPosition > cnt)
{
bDownShift = TRUE;
pASMSourceInfo->m_pStreams[0]->m_ulThresholdPosition = cnt;
}
// We are upshifting
else if ((int)pASMSourceInfo->m_pStreams[0]->m_ulThresholdPosition < cnt)
pASMSourceInfo->m_bTryToUpShift = TRUE;
pASMSourceInfo->m_pStreams[0]->m_ulMaxEffectiveThreshold = cnt;
break;
}
}
if (bDownShift || pASMSourceInfo->m_bTryToUpShift)
pASMSourceInfo->m_bAdjustBandwidth = TRUE;
}
m_State = REDIST;
RecalcAccel();
}
}
HX_ASSERT(bSourceFound);
return HXR_OK;
}
void
HXSM::Recalc()
{
CHXSimpleList::Iterator i, j;
ASMSourceInfo* pASMSourceInfo;
ASMStreamInfo* pASMStreamInfo;
INT32 lAggregateBandwidthUsage = 0;
INT32 lAggregateBandwidthSent = 0;
UINT32 ulSourceCount;
UINT32 ulStreamCount;
float fBiasMean = (float) 0.;
ulSourceCount = m_pASMSourceInfo->GetCount();
ulStreamCount = m_pASMStreamInfo->GetCount();
for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
{
pASMSourceInfo = (ASMSourceInfo*)(*i);
/* Init these for later */
pASMSourceInfo->m_ulMasterOffer = 0;
pASMSourceInfo->m_bTimeStampDelivery = FALSE;
}
lAggregateBandwidthUsage = m_ulOfferToRecalc;
INT32 lCorrectAggregateBandwidthUsage = lAggregateBandwidthUsage;
/*
* For each stream that is at a fixed bitrate, remove that bitrate
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -