📄 hxsm.cpp
字号:
ulNewValue = ulSourceBandwidth;
}
if ((HXR_OK == pASMSourceInfo->m_pSource->
QueryInterface(IID_IHXThinnableSource, (void **)&pThin)))
{
if (ulNewValue < (pASMSourceInfo->m_ulLastSetDelivery))
{
DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
"(%p)Congestion: Slow Tranmission Rate to %d %p", pASMSourceInfo->m_pSource,
ulNewValue, pASMSourceInfo));
if (pASMSourceInfo->m_bLossBehind)
{
pASMSourceInfo->m_ulIncomingBandwidth = ulNewValue;
bLossBehind = TRUE;
}
if (pASMSourceInfo->m_ulRateBeforeDeAccel)
{
pASMSourceInfo->m_ulRateBeforeDeAccel = ulNewValue;
/*
* Reset the core's acceleration status.
*/
IHXWatermarkBufferControl* pWMBufCtl = NULL;
pASMSourceInfo->m_pSource->
QueryInterface(IID_IHXWatermarkBufferControl,
(void**)&pWMBufCtl);
if (pWMBufCtl)
{
pWMBufCtl->ClearChillState();
pWMBufCtl->Release();
pWMBufCtl = NULL;
}
pASMSourceInfo->m_bMayBeAccelerated = TRUE;
pASMSourceInfo->m_bPendingChill = FALSE;
}
if ((ulNewValue < ulSourceBandwidth) && (ulSourceBandwidth > 10))
{
pASMSourceInfo->m_pSource->EnterBufferedPlay();
}
pASMSourceInfo->m_ulLastSetDelivery = ulNewValue;
ulTotalBandwidth += ulNewValue;
UINT32 ulActualRate = ulNewValue;
/*
* Always keep TCP traffic faster then needed
* (but keep it quiet so the rest of the algorithm doesn't
* find out :-)
*/
if (pASMSourceInfo->m_TransportType == TNG_TCP)
{
ulActualRate = MAX(ulActualRate,
(UINT32)(ulSourceBandwidth * 1.10));
}
// In low heap mode, do not change the delivery bw.
// NOTE: There is concern that this is not
// satisfactory as a truly long term solution since
// bw rate control is regarded by some as critical
// for limited resource platforms.
#if !defined(HELIX_CONFIG_LOW_HEAP_STREAMING)
pThin->SetDeliveryBandwidth(ulActualRate, 0);
#endif
}
else
{
ulTotalBandwidth +=
pASMSourceInfo->m_ulLastSetDelivery;
}
}
HX_RELEASE(pThin);
}
if (bLossBehind)
{
m_ulNumReportsSinceUpShift = -10;
m_ulResistanceBitRate = MAX(15000, ulTotalBandwidth);
DEBUG_OUT(m_pEM, DOL_TRANSPORT,
(s, "Resistance Move %d", m_ulResistanceBitRate));
}
}
}
else if (!ulNumSlightlyBehindSources)
{
INT32 lAccelTestPoint;
double dRFactor = 1.05;
if ((INT32)m_ulUpShiftBandwidthAvail > lAggregateBandwidthUsage)
{
lAccelTestPoint = (INT32)
((m_ulUpShiftBandwidthAvail - lAggregateBandwidthUsage)
* ((float)m_ulUpShiftTestPointScaleFactor / 10000.0)
+ lAggregateBandwidthUsage);
}
else
{
lAccelTestPoint = lAggregateBandwidthUsage;
}
UINT32 ulAccelTestPoint =
(lAccelTestPoint > 0) ? (UINT32)lAccelTestPoint : 0;
BOOL bResistanceLimited = FALSE;
BOOL bWentHigherThanResistanceRate = FALSE;
if (ulAccelTestPoint > m_ulMaxAccelBitRate)
{
ulAccelTestPoint = m_ulMaxAccelBitRate;
}
if (ulAccelTestPoint > m_ulResistanceBitRate)
{
UINT32 ulActualResistanceBitRate = m_ulResistanceBitRate;
if (ulActualResistanceBitRate < ulAggregateUsed)
{
ulActualResistanceBitRate = (UINT32)(ulAggregateUsed * 1.05);
}
UINT32 ulOldAccelTestPoint = ulAccelTestPoint;
if (ulAccelTestPoint > ulActualResistanceBitRate)
{
UINT32 bHowManyReports =
(ulActualResistanceBitRate <
ulTotalMaxSubscribedBw) ? 5 : 10;
if (m_ulUpShiftPastResistanceCount > bHowManyReports)
{
bWentHigherThanResistanceRate = TRUE;
if ((m_ulOriginalResistanceBitRate >
ulActualResistanceBitRate) &&
(ulActualResistanceBitRate < ulTotalMaxSubscribedBw))
{
dRFactor = (ulActualResistanceBitRate +
((m_ulOriginalResistanceBitRate -
ulActualResistanceBitRate) * 0.10)) /
(double)ulActualResistanceBitRate;
if (dRFactor < 1.01)
{
dRFactor = 1.01;
}
#ifdef MOREDEBUG
DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
"Resistance Accel Factor %0.2f", dRFactor));
#endif
}
else
{
dRFactor = 1.01;
}
ulAccelTestPoint = (UINT32)(ulActualResistanceBitRate *
dRFactor);
}
else
{
ulAccelTestPoint = ulActualResistanceBitRate;
}
if (ulOldAccelTestPoint < ulAccelTestPoint)
{
ulAccelTestPoint = ulOldAccelTestPoint;
}
else
{
bResistanceLimited = TRUE;
}
}
}
if ((m_ulNumReportsSinceUpShift >= 2) &&
((INT32)m_ulHighestBandwidthAvail < lAggregateBandwidthUsage))
{
m_ulHighestBandwidthAvail = lAggregateBandwidthUsage;
m_ulPeakUsedBandwidth = lAggregateBandwidthUsage;
m_bInitialHighBwAvail = FALSE;
}
DEBUG_OUT(m_pEM, DOL_TRANSPORT_EXTENDED,
(s, "UP Bw Report: Num=%d, Avail=%d, CurrentBw=%d, TestPoint=%d",
m_ulNumReportsSinceUpShift, m_ulUpShiftBandwidthAvail,
lAggregateBandwidthUsage, ulAccelTestPoint));
BOOL bDidChange = FALSE;
BOOL bBrokeMax = FALSE;
if ((m_ulNumReportsSinceUpShift >= 2) &&
(INT32) (ulAccelTestPoint) > lAggregateBandwidthUsage)
{
m_ulLastStableBandwidth = lAggregateBandwidthUsage;
for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
{
pASMSourceInfo = (ASMSourceInfo*)(*i);
IHXThinnableSource* pThin = 0;
UINT32 ulSourceBandwidth = pASMSourceInfo->m_ulSubscribedBw;
UINT32 ulNewValue =
(UINT32)(
(float)ulSourceBandwidth /
(float)ulAggregateUsed *
(float)ulAccelTestPoint);
if (ulNewValue > (pASMSourceInfo->m_ulMaxSubscribedBw * 4))
{
ulNewValue = (UINT32)
(pASMSourceInfo->m_ulMaxSubscribedBw * 4);
}
/*
* Live streams get capped at 107% of Max to prevent
* unneeded bandwidht modulation.
*/
if ((pASMSourceInfo->m_pSource->IsLive()) &&
(ulNewValue >
(pASMSourceInfo->m_ulMaxSubscribedBw * 1.07)))
{
ulNewValue = (UINT32)
(pASMSourceInfo->m_ulMaxSubscribedBw * 1.07);
}
if ((ulNewValue > (pASMSourceInfo->m_ulMaxSubscribedBw)) &&
(ulNewValue > (ulSourceBandwidth * 3)) &&
(pASMSourceInfo->m_ulLastSetDelivery <
pASMSourceInfo->m_ulMaxSubscribedBw))
{
/*
* If we are already accelerating 3x subscribed bandwidth
* and we are about to upshift beyond the max possible
* bandwidth, then let's stop and take a breather just
* above the max subscription. This prevents us from
* buffering huge amounts of the crappy low bw stream.
*/
UINT32 ulTemp;
ulTemp = (UINT32)
(pASMSourceInfo->m_ulMaxSubscribedBw * 1.10);
ulNewValue = MIN(ulTemp, ulNewValue);
}
if (pASMSourceInfo->m_ulLastSetDelivery >
pASMSourceInfo->m_ulMaxSubscribedBw)
{
bBrokeMax = TRUE;
}
if (pASMSourceInfo->m_bMayBeAccelerated &&
(HXR_OK == pASMSourceInfo->m_pSource->
QueryInterface(IID_IHXThinnableSource, (void **)&pThin)))
{
double Factor;
if (bResistanceLimited)
{
Factor = 1.005;
}
else if (pASMSourceInfo->m_pSource->IsLive())
{
Factor = 1.01;
}
else
{
Factor = 1.05;
}
if ((ulNewValue > (pASMSourceInfo->m_ulLastSetDelivery * Factor)) &&
pASMSourceInfo->m_bSourceAccelAllowed)
{
DEBUG_OUT(m_pEM, DOL_TRANSPORT,
(s, "(%p)Accelerating: NewTransmissionRate=%d", pASMSourceInfo->m_pSource, ulNewValue));
m_ulUpShiftPastResistanceCount = 0;
if (ulNewValue > ulSourceBandwidth)
{
pASMSourceInfo->m_pSource->LeaveBufferedPlay();
}
bDidChange = TRUE;
/*
* WHOA! If this is a timestamp delivered source
* i.e. 5.0 thinning, then the imperical Getbandwidth()
* will never reach the rate that we set, so we help
* it along a bit (just a bit of a nudge, eh?).
*/
if (pASMSourceInfo->m_bTimeStampDelivery)
{
pASMSourceInfo->m_ulIncomingBandwidth = ulNewValue;
}
m_ulNumReportsSinceUpShift = 0;
pASMSourceInfo->m_bInvalidUpReport = TRUE;
m_bDidOfferUpShiftToRecalc = FALSE;
pThin->SetDeliveryBandwidth(
(pASMSourceInfo->m_ulLastSetDelivery = ulNewValue), 0);
}
}
HX_RELEASE(pThin);
}
}
if ((bDidChange == TRUE) && (bWentHigherThanResistanceRate))
{
m_ulResistanceBitRate = (UINT32)(m_ulResistanceBitRate * dRFactor);
DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
"Went over ResistanceBitRate %d", m_ulResistanceBitRate));
}
if (((bDidChange == FALSE) &&
(m_ulNumReportsSinceUpShift > NUM_REPORTS_NEEDED_TO_UPSHIFT) ||
(bBrokeMax == TRUE)) && (m_bDidOfferUpShiftToRecalc == FALSE))
{
m_State = HX_NONE;
m_bDidOfferUpShiftToRecalc = TRUE;
m_ulOfferToRecalc = lAggregateBandwidthUsage;
#ifdef MOREDEBUG
DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
"Upshift Offer to Recalc() %d", m_ulOfferToRecalc));
#endif
Recalc();
return;
}
}
}
void
ASMStreamInfo::NotifyNewBandwidth()
{
m_pNegotiator->SetBandwidthUsage(m_ulLastBandwidth,
m_bTimeStampDelivery);
}
void
ASMStreamInfo::NotifyTimeStampDelivery()
{
if(m_bTimeStampDelivery)
{
m_pASMSourceInfo->m_bTimeStampDelivery = TRUE;
}
}
UINT32
ASMSourceInfo::GetBandwidth()
{
return m_ulIncomingBandwidth;
}
void
ASMStreamInfo::SetLastBandwidth(UINT32 ulOffer)
{
m_ulLastBandwidth = ulOffer;
}
void
ASMStreamInfo::NotifyLimitBandwidth(UINT32 ulRecv)
{
if(m_pASMSourceInfo->m_bBehind)
{
m_pNegotiator->HandleSlowSource(ulRecv);
}
}
ASMSourceInfo::ASMSourceInfo(HXSource* pSource, HXSM* pHXASM)
: m_ulLastReportTime(0)
, m_ulIncomingBandwidth(0)
, m_ulRateBeforeDeAccel(0)
, m_lTimeDiffBase(0)
, m_ulBytesBehind(0)
, m_lLastBehindTime(0)
, m_ulLastSetDelivery(0xffffffff)
, m_ulSubscribedBw(0)
, m_ulMaxSubscribedBw(0)
, m_bBehind(FALSE)
, m_bLossBehind(FALSE)
, m_bSlightlyBehind(FALSE)
, m_bTimeStampDelivery(FALSE)
, m_bPendingChill(FALSE)
, m_bInvalidUpReport(FALSE)
, m_bPerfectPlay(FALSE)
, m_bIsDone(FALSE)
, m_bMayBeAccelerated(TRUE)
, m_bTryToUpShift(FALSE)
, m_bAdjustBandwidth(FALSE)
, m_ulLowestBandwidthBeforeTimeStamp(0)
, m_bSourceAccelAllowed(TRUE)
, m_bSourceDecelAllowed (TRUE)
, m_bSlidingBwWindowReady(FALSE)
, m_pMasterRuleBook(0)
, m_pStreams(0)
, m_TransportType(TNG_UDP)
, m_pSource(pSource)
, m_pSBI(0)
, THRESHOLD(1000)
, m_lRefCount(0)
, m_ulBwDetectionDataCount(0)
, m_ulBwDetectionDataLen(0)
, m_ulSlidingWindowLocation(0)
, m_pBwDetectionData(NULL)
, m_pHXASM(pHXASM)
{
m_lOuterThreshold = THRESHOLD;
IHXValues* pHeader = 0;
pSource->AddRef();
if (pSource->m_pFileHeader)
{
IHXBuffer* pMasterRuleBook = NULL;
pSource->m_pFileHeader->
GetPropertyCString("ASMRuleBook", pMasterRuleBook);
if (pMasterRuleBook)
{
m_pMasterRuleBook = new ASMRuleBook
((const char *)pMasterRuleBook->GetBuffer());
}
HX_RELEASE(pMasterRuleBook);
}
}
ASMSourceInfo::~ASMSourceInfo()
{
HX_VECTOR_DELETE(m_pBwDetectionData);
delete[] m_pStreams;
delete m_pMasterRuleBook;
}
BOOL
ASMSourceInfo::AllocBWDetectionData(UINT32 ulReqSize)
{
BOOL bOk = TRUE;
// Our current array is too small
if (ulReqSize > m_ulBwDetectionDataLen)
{
BwDetectionData* pTemp = new
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -