📄 hxsm2.cpp
字号:
inlineBOOL ASMStreamInfo2::IsFixedBw() const{ return (m_ulFixedBandwidth != 0);}UINT32 ASMStreamInfo2::CurrentBw() const{ UINT32 ulRet = (m_bFixedBwValid) ? m_ulFixedBandwidth : 0; if (!ulRet && m_pThresholds) { ulRet = (UINT32)m_pThresholds[m_ulCurThresh]; } return ulRet;}inlineUINT32 ASMStreamInfo2::StreamID() const{ return m_ulStreamID;}inlinevoid ASMStreamInfo2::SetStreamOffer(UINT32 ulOffer){ m_ulStreamOffer = ulOffer;}void ASMStreamInfo2::SelectBw(BOOL bPerfectPlay, UINT32 ulAltOffer){ if (m_pThresholds) { if (bPerfectPlay) { /* * If we are in perfect play mode, just select the highest bandwidth rule * and don't negotiate any further. */ m_ulCurThresh = m_ulMaxEffectiveThreshold; m_ulOffer = CurrentBw(); } else { UINT32 ulOffer = ulAltOffer; if (m_ulStreamOffer) { ulOffer = m_ulStreamOffer - 1; } if (m_ulMaxEffectiveThreshold != 0) { for (UINT32 i = 1; i <= m_ulMaxEffectiveThreshold; i++) { if ((ulOffer <= m_pThresholds[i]) || (i == m_ulMaxEffectiveThreshold)) { m_ulOffer = ulOffer; m_ulCurThresh = i; break; } } } } ComputeResistence(bPerfectPlay); }}inlineUINT32 ASMStreamInfo2::ResistanceToLower() const{ return m_ulResistanceToLower;}void ASMStreamInfo2::SelectNextLowerBw(){ if (m_ulCurThresh > 0) { m_ulCurThresh--; ComputeResistence(FALSE); }}inlineUINT32 ASMStreamInfo2::GetLastBw() const{ return m_ulLastBw;}void ASMStreamInfo2::SubscribeToNewBw(UINT32 ulBw, CHXSimpleList* pSubChanges){ BOOL bTimeStampDelivery = FALSE; if (m_pRuleGather && m_pNegotiator) { m_pRuleGather->RuleGather(pSubChanges); //update the HXASMStream with our new bandwidth m_pNegotiator->SetBandwidthUsage(ulBw, bTimeStampDelivery); m_pRuleGather->RuleGather(0); } m_ulLastBw = ulBw;}void ASMStreamInfo2::SubscribeToChanges(CHXSimpleList* pSubChanges){ if (m_pRuleGather) { m_pRuleGather->RuleFlush(pSubChanges); }}void ASMStreamInfo2::ComputeResistence(BOOL bPerfectPlay){ /* NOTE: * m_ulCurThresh and m_ulOffer must * be valid when this function is called */ if (IsFixedBw() || bPerfectPlay || (m_ulMaxEffectiveThreshold == 0) || (m_ulCurThresh == 1)) { m_ulResistanceToLower = 0xffffffff; } else { m_ulResistanceToLower = (m_ulOffer - (UINT32)m_pThresholds[m_ulCurThresh - 1]) * m_ulOffer; }}HXSM2::HXSM2() : m_lRefCount(0), m_ulNumSources(0), m_pASMSourceInfo(0), m_ulNumStreams(0), m_ulOfferToRecalc(0), m_ulSelectionBitRate(0), m_ulMaxAccelBitRate(0), m_ulSustainableBitRate(0), m_pSubscriptionVariables(0), m_bCheckOnDemandBw(FALSE){ m_pASMSourceInfo = new CHXSimpleList();}HXSM2::~HXSM2(){ if (m_pASMSourceInfo) { while(!m_pASMSourceInfo->IsEmpty()) { ASMSourceInfo2* pSrc = (ASMSourceInfo2*)m_pASMSourceInfo->RemoveHead(); delete pSrc; } delete m_pASMSourceInfo; }}STDMETHODIMP HXSM2::QueryInterface(THIS_ REFIID ID, void** ppInterfaceObj){ QInterfaceList qiList[] = { { GET_IIDHANDLE(IID_IUnknown), this }, { GET_IIDHANDLE(IID_IHXBandwidthManager), (IHXBandwidthManager*) this }, }; return QIFind(qiList, QILISTSIZE(qiList), ID, ppInterfaceObj);}STDMETHODIMP_(UINT32) HXSM2::AddRef(THIS){ return InterlockedIncrement(&m_lRefCount);}STDMETHODIMP_(UINT32) HXSM2::Release(THIS){ if (InterlockedDecrement(&m_lRefCount) > 0) { return m_lRefCount; } delete this; return 0;}/* * IHXBandwidthManager methods */STDMETHODIMP HXSM2::RegisterSource(THIS_ HXSource* pSource, IUnknown* pUnknown){ HX_RESULT res = HXR_OK; IHXSourceBandwidthInfo* pSBI; IHXPreferences* pPreferences = NULL; IHXBuffer* pBuffer = 0; ASMSourceInfo2* pASMSourceInfo = NULL; if (HXR_OK == pSource->QueryInterface(IID_IHXSourceBandwidthInfo, (void **)&pSBI)) { pASMSourceInfo = new ASMSourceInfo2(pSource); m_ulNumSources++; m_ulNumStreams += pASMSourceInfo->StreamCount(); m_pASMSourceInfo->AddTail((void *)pASMSourceInfo); HX_RELEASE(pSBI); } else { return HXR_OK; } /* * This variable tells us the highest amount of bandwidth that we * believe is useable. If we stream thin, then the highest value * that the pipe can support would be the aggregate bandwidth of * the sources. Barring any thinning, this would be the bandwidth * from prefs (unless we can determine it through fast buffering or * another transport feature). This value is used when starting sources * as a initial guess for bandwidth (to set subscriptions). */ if (m_ulSelectionBitRate == 0) { pUnknown->QueryInterface(IID_IHXPreferences, (void **)&pPreferences); UINT32 ulTemp = 0; UINT32 ulConnectionBw = 10485760; /* wild guess */ /* Get initial bandwidth guess from Prefs */ if ((HXR_OK == ReadPrefINT32(pPreferences, "Bandwidth", ulTemp)) && (ulTemp > 0)) { ulConnectionBw = ulTemp; } /* * m_ulSustainableBitRate refers to the max bitrate that we believe is * sustainable over the connection. The client should never ask * the server to send bits faster than this rate because it could * cause congestion collapse. * * m_ulSelectionBitRate refers to the highest bitrate stream that we'll * ever try to play. Note that people can choose to pick values * where m_ulSelectionBitRate > m_ulSustainableBitRate. This may * cause rebuffers because the delivery will be capped at * m_ulSustainableBitRate. Why would someone do that? They may accept * rebuffers if it means they get a higher quality presentation. */ /* See if we have a sustainable bandwidth factor */ if (HXR_OK == ReadPrefINT32(pPreferences, "SustainableBwFactor", ulTemp)) { /* clamp value to 0 <= ulTemp <= 100 range */ if (ulTemp > 100) { ulTemp = 100; } /* Apply factor */ m_ulSustainableBitRate = (((ulConnectionBw / 100) * ulTemp) + (((ulConnectionBw % 100) * ulTemp) / 100)); } else { m_ulSustainableBitRate = ulConnectionBw; } /* See if we have a selection bandwidth factor */ if (HXR_OK == ReadPrefINT32(pPreferences, "SelectionBwFactor", ulTemp)) { /* clamp value to 0 <= ulTemp <= 200 range */ if (ulTemp > 200) { ulTemp = 200; } /* Apply factor */ m_ulSelectionBitRate = (((m_ulSustainableBitRate / 100) * ulTemp) + (((m_ulSustainableBitRate % 100) * ulTemp) / 100)); } else { m_ulSelectionBitRate = m_ulSustainableBitRate; } /* Get MaxBandwidth from Prefs */ if (HXR_OK != ReadPrefINT32(pPreferences, "MaxBandwidth", m_ulMaxAccelBitRate)) { /* * Failed to get the MaxBandwidth preference. * Use m_ulSelectionBitRate value instead. */ m_ulMaxAccelBitRate = m_ulSelectionBitRate; } /* * Get preference that controls whether we report * "not enough bandwidth" conditions for on-demand clips */ ReadPrefBOOL(pPreferences, "CheckOnDemandBw", m_bCheckOnDemandBw); HX_RELEASE(pPreferences); } return res;}STDMETHODIMP HXSM2::RegisterSourcesDone(THIS){ CHXSimpleList::Iterator i; ASMSourceInfo2* pASMSourceInfo; for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i) { pASMSourceInfo = (ASMSourceInfo2*)(*i); if (pASMSourceInfo) { pASMSourceInfo->LastSetDelivery() = 0; } } m_ulOfferToRecalc = m_ulSelectionBitRate; if (m_ulOfferToRecalc > m_ulMaxAccelBitRate) { m_ulOfferToRecalc = m_ulMaxAccelBitRate; } Recalc(); return HXR_OK;} STDMETHODIMP_(BOOL) HXSM2::NotEnoughBandwidth(THIS){ CHXSimpleList::Iterator i; ASMSourceInfo2* pASMSourceInfo; UINT32 ulTotal = 0; BOOL bCheckTotal = m_bCheckOnDemandBw; for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i) { pASMSourceInfo = (ASMSourceInfo2*)(*i); ulTotal += pASMSourceInfo->SubscribeBw(); if (pASMSourceInfo->IsLive()) { bCheckTotal = TRUE; } } if (bCheckTotal && ulTotal > m_ulSelectionBitRate) { return TRUE; } else { return FALSE; }}STDMETHODIMP HXSM2::UnRegisterSource(THIS_ HXSource* pSource){ LISTPOSITION lPos; ASMSourceInfo2* pASMSourceInfo = 0; BOOL bFound = FALSE; lPos = m_pASMSourceInfo->GetHeadPosition(); while (lPos) { pASMSourceInfo = (ASMSourceInfo2*)m_pASMSourceInfo->GetAt(lPos); if (pASMSourceInfo->IsMySource(pSource)) { m_pASMSourceInfo->RemoveAt(lPos); pASMSourceInfo->Done(); bFound = TRUE; break; } m_pASMSourceInfo->GetNext(lPos); } if (bFound) { m_ulNumStreams -= pASMSourceInfo->StreamCount(); delete pASMSourceInfo; m_ulNumSources--; if (m_ulNumSources > 0) { Recalc(); } } return HXR_OK;}STDMETHODIMP HXSM2::ChangeAccelerationStatus(THIS_ HXSource* pSource, BOOL bMayBeAccelerated, BOOL bUseAccelerationFactor, UINT32 ulAccelerationFactor){ return HXR_OK;} /* Called by HXPlayer at end of each presentation */STDMETHODIMP HXSM2::PresentationDone(THIS){ return HXR_OK;} STDMETHODIMP HXSM2::ChangeBW(THIS_ UINT32 newBW, HXSource* pSource){ return HXR_OK;}voidHXSM2::Recalc(){ CHXSimpleList::Iterator i; ASMStreamInfoItr streamItr(m_pASMSourceInfo); ASMSourceInfo2* pASMSourceInfo; ASMStreamInfo2* pASMStreamInfo; INT32 lAggregateBandwidthUsage = 0; UINT32 ulSourceCount; UINT32 ulStreamCount; float fBiasMean = (float) 0.; ulSourceCount = m_pASMSourceInfo->GetCount(); ulStreamCount = m_ulNumStreams; for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i) { pASMSourceInfo = (ASMSourceInfo2*)(*i); /* Init these for later */ pASMSourceInfo->MasterOffer() = 0; } lAggregateBandwidthUsage = m_ulOfferToRecalc; INT32 lCorrectAggregateBandwidthUsage = lAggregateBandwidthUsage; /* * For each stream that is at a fixed bitrate, remove that bitrate * from our available bandwidth. */ for (streamItr.Reset(); streamItr.More(); streamItr.Next()) { INT32 lBias; pASMStreamInfo = streamItr.Stream(); HX_VERIFY(HXR_OK == pASMStreamInfo->GetBiasFactor(lBias)); fBiasMean += lBias; if (pASMStreamInfo->IsFixedBw()) { lAggregateBandwidthUsage -= pASMStreamInfo->CurrentBw(); ulStreamCount--; } /* Init this for later */ pASMStreamInfo->SetStreamOffer(0); } if (ulStreamCount != 0) { /* At least 1 stream is not fixed bandwidth */ fBiasMean /= ulStreamCount; /* * Calculate the offer for each source that has a master rulebook * defining it's bandwidth division. */ INT32 lNewAggregateBandwidthUsage = lAggregateBandwidthUsage; for (streamItr.Reset(); streamItr.More(); streamItr.Next()) { INT32 lBias; pASMStreamInfo = streamItr.Stream(); pASMSourceInfo = streamItr.Source(); HX_VERIFY(HXR_OK == pASMStreamInfo->GetBiasFactor(lBias)); if (pASMSourceInfo->HasMasterRuleBook()) { UINT32 ulOffer = (UINT32)(lAggregateBandwidthUsage / ulStreamCount); ulOffer += (UINT32)(((float)lBias - fBiasMean) * ((float)lAggregateBandwidthUsage / 100.0) * (2.0 / ulStreamCount)); pASMSourceInfo->MasterOffer() += ulOffer; lNewAggregateBandwidthUsage -= ulOffer; } } lAggregateBandwidthUsage = lNewAggregateBandwidthUsage; } /* * For each source that has a master rule book, evaluate it to find * out how much to distribute to each stream. */ for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i) { pASMSourceInfo = (ASMSourceInfo2*)(*i); if (pASMSourceInfo->HasMasterRuleBook()) { pASMSourceInfo->DistributeBw(); } } /* * Now go through each of the streams that are not at a * fixed bitrate and try to distribute the rest of the bandwidth. */ UINT32 ulTakenBandwidth = 0; for (streamItr.Reset(); streamItr.More(); streamItr.Next()) { pASMStreamInfo = streamItr.Stream(); if (!pASMStreamInfo->IsFixedBw()) { INT32 lBias; HX_VERIFY(HXR_OK == pASMStreamInfo->GetBiasFactor(lBias)); UINT32 ulAltOffer = (UINT32)(lAggregateBandwidthUsage / (float)ulStreamCount); ulAltOffer += (UINT32)(((float)lBias - fBiasMean) * ((float)lAggregateBandwidthUsage / 100.0) * (2.0 / (float)ulStreamCount)); pASMStreamInfo->SelectBw(streamItr.Source()->IsPerfectPlay(), ulAltOffer); } ulTakenBandwidth += pASMStreamInfo->CurrentBw(); } lAggregateBandwidthUsage = lCorrectAggregateBandwidthUsage; BOOL bDone = FALSE; while (!bDone && (lAggregateBandwidthUsage < (INT32)ulTakenBandwidth)) { /* Resistance is Futile. You will be Real(tm)lyAssimilated */ UINT32 ulLowestResistance = 0xffffffff; ASMStreamInfo2* pLowestResistanceStream = 0; // Find the stream with the lowest resistence for (streamItr.Reset(); streamItr.More(); streamItr.Next()) { pASMStreamInfo = streamItr.Stream(); if (pASMStreamInfo->ResistanceToLower() < ulLowestResistance) { ulLowestResistance = pASMStreamInfo->ResistanceToLower(); pLowestResistanceStream = pASMStreamInfo; } } if (ulLowestResistance == 0xffffffff) { bDone = TRUE; } else { ulTakenBandwidth -= (UINT32) pLowestResistanceStream->CurrentBw(); pLowestResistanceStream->SelectNextLowerBw(); ulTakenBandwidth += (UINT32) pLowestResistanceStream->CurrentBw(); } } UINT32 ulLeftOverForDropByN = lAggregateBandwidthUsage - ulTakenBandwidth; BOOL bForce = FALSE; for (streamItr.Reset(); streamItr.More(); streamItr.Next()) { pASMStreamInfo = streamItr.Stream(); UINT32 ulBw = pASMStreamInfo->CurrentBw(); if (ulBw == 1) { // Hack Alert for DropByN. XXXSMP ulBw = ulLeftOverForDropByN; } if ((ulBw != pASMStreamInfo->GetLastBw()) && (pASMStreamInfo->IsFixedBw())) { bForce = TRUE; } CHXSimpleList* pSubsChanges = streamItr.Source()->SubsChanges(); pASMStreamInfo->SubscribeToNewBw(ulBw, pSubsChanges); } for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i) { pASMSourceInfo = (ASMSourceInfo2*)(*i); pASMSourceInfo->SubscribeToChanges(); pASMSourceInfo->SetDeliveryBw(m_ulSustainableBitRate); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -