hxsm.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:84k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: hxsm.cpp,v 1.17.2.1 2004/07/09 02:05:30 hubbe Exp $
- *
- * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file,
- * are subject to the current version of the RealNetworks Public
- * Source License (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (the "RCSL") available at
- * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
- * will apply. You may also obtain the license terms directly from
- * RealNetworks. You may not use this file except in compliance with
- * the RPSL or, if you have a valid RCSL with RealNetworks applicable
- * to this file, the RCSL. Please see the applicable RPSL or RCSL for
- * the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the
- * portions it created.
- *
- * This file, and the files included with this file, is distributed
- * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
- * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
- * ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- /*
- *
- * ASM Manager for all streams in all Players.
- *
- * This class will manage the bandwidth requirements
- * of multiple streams.
- */
- #include "hlxclib/stdio.h" /* printf */
- #include "hlxclib/stdlib.h" /* atoi on Mac */
- #include "hxtypes.h" /* Basic Types */
- #include "hxcom.h" /* IUnknown */
- #include "hxslist.h"
- #include "hxerror.h"
- #include "hxsmbw.h"
- #include "hxsm.h" /* HXSM */
- #include "hxsmutil.h"
- #include "hxpref.h"
- #include "ihxpckts.h"
- #include "hxcore.h"
- #include "asmrulep.h"
- #include "hxbuffer.h"
- #include "chxpckts.h"
- #include "hxbsrc.h"
- #include "hxsrc.h"
- #include "errdbg.h"
- #include "rtspif.h"
- #include "hxurl.h"
- #include "hxtick.h"
- #include "hxstrutl.h"
- #include "hxbufctl.h"
- #include "hxheap.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #endif
- #ifndef MIN
- #define MIN(x, y) (((x) < (y)) ? (x) : (y))
- #endif
- #ifndef MAX
- #define MAX(x, y) (((x) > (y)) ? (x) : (y))
- #endif
- HXSM::HXSM()
- : m_State(HX_NONE)
- , m_lRefCount(0)
- , m_pSubscriptionVariables(0)
- , m_ulOriginalHighestBandwidthAvail(0)
- , m_ulHighestBandwidthAvail(0)
- , m_ulPeakUsedBandwidth(0)
- , m_ulUpShiftRingPos(0)
- , m_ulUpShiftBandwidthAvail(0)
- , m_ulNumSources(0)
- , m_ulMaxAccelBitRate(0xffffffff)
- , m_ulNumReportsSinceUpShift(2)
- , m_ulLastStableBandwidth(0)
- , m_ulUpShiftTestPointScaleFactor(4000)
- , m_ulOfferToRecalc(0)
- , m_ulNextPacketWindow(0)
- , m_lPacketCounter(0)
- , m_ulUpShiftPastResistanceCount(0)
- , m_lLoss(0)
- , m_bInitialHighBwAvail(TRUE)
- , m_bPipeFull(FALSE)
- , m_bUpShiftInfoReady(FALSE)
- , m_bDidOfferUpShiftToRecalc(FALSE)
- , m_bLoadTest(FALSE)
- , m_bDoAccel(TRUE)
- , m_bDoDecel(TRUE)
- , m_bDisableBothAccelDecel(FALSE)
- , m_fAccelerationFactor(4.0)
- , m_bEnableSDB(TRUE)
- #ifndef GOLD
- , m_pEM(0)
- #endif
- {
- m_pASMSourceInfo = new CHXSimpleList;
- m_pASMStreamInfo = new CHXSimpleList;
- }
- HXSM::~HXSM()
- {
- #ifndef GOLD
- HX_RELEASE(m_pEM);
- #endif
- CHXSimpleList::Iterator i;
- ASMSourceInfo* pASMSourceInfo;
- ASMStreamInfo* pASMStreamInfo;
- for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
- {
- pASMSourceInfo = (ASMSourceInfo*)(*i);
- pASMSourceInfo->Release();
- }
- for (i = m_pASMStreamInfo->Begin(); i != m_pASMStreamInfo->End(); ++i)
- {
- pASMStreamInfo = (ASMStreamInfo*)(*i);
- delete pASMStreamInfo;
- }
- delete m_pASMSourceInfo;
- delete m_pASMStreamInfo;
- HX_RELEASE(m_pSubscriptionVariables);
- }
- STDMETHODIMP_(UINT32)
- HXSM::AddRef(void)
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- STDMETHODIMP_(UINT32)
- HXSM::Release(void)
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- STDMETHODIMP
- HXSM::QueryInterface
- (
- REFIID interfaceID,
- void** ppInterfaceObj
- )
- {
- QInterfaceList qiList[] =
- {
- { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)this },
- { GET_IIDHANDLE(IID_IHXBandwidthManager), (IHXBandwidthManager*)this },
- };
-
- return ::QIFind(qiList, QILISTSIZE(qiList), interfaceID, ppInterfaceObj);
- }
- STDMETHODIMP
- HXSM::RegisterSource(HXSource* pSource, IUnknown* pUnknown)
- {
- IHXSourceBandwidthInfo* pSBI;
- IHXPreferences* pPreferences = NULL;
- ASMSourceInfo* pASMSourceInfo = NULL;
- UINT16 i;
- #ifndef GOLD
- HX_RELEASE(m_pEM);
- pUnknown->QueryInterface(IID_IHXErrorMessages, (void **)&m_pEM);
- #endif
- DEBUG_OUT(m_pEM, DOL_BWMGR, (s, "Register Source %p %s", pSource, pSource->GetURL()));
- if (HXR_OK == pSource->QueryInterface(IID_IHXSourceBandwidthInfo,
- (void **)&pSBI))
- {
- pASMSourceInfo = new ASMSourceInfo(pSource, this);
- pASMSourceInfo->AddRef();
- pASMSourceInfo->m_pSBI = pSBI;
- /* Local source is always considered in perfect play mode UNLESS we are
- * in simulated network playback mode (used Preview mode in the Encoder)
- */
- pASMSourceInfo->m_bPerfectPlay = pSource->IsPerfectPlay() && !pSource->IsSimulatedNetworkPlayback();
- m_ulNumSources++;
- m_pASMSourceInfo->AddTail((void *)pASMSourceInfo);
- pSBI->InitBw(pASMSourceInfo);
- }
- 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_ulHighestBandwidthAvail == 0)
- {
- pUnknown->QueryInterface(IID_IHXPreferences, (void **)&pPreferences);
- UINT32 ulTemp = 0;
- /* Get initial bandwidth guess from Prefs */
- if (HXR_OK == ReadPrefINT32(pPreferences, "Bandwidth", ulTemp))
- {
- m_bInitialHighBwAvail = TRUE;
- /* Translate the bandwidth from prefs into a starting point */
- if (ulTemp == 14400) m_ulHighestBandwidthAvail = 11000;
- else if (ulTemp == 19200) m_ulHighestBandwidthAvail = 14400;
- else if (ulTemp == 28800) m_ulHighestBandwidthAvail = 21600;
- else if (ulTemp == 33600) m_ulHighestBandwidthAvail = 25000;
- else if (ulTemp == 34400) m_ulHighestBandwidthAvail = 34400;
- else if (ulTemp == 57600) m_ulHighestBandwidthAvail = 50000;
- else if (ulTemp == 65536) m_ulHighestBandwidthAvail = 56360;
- else if (ulTemp == 115200) m_ulHighestBandwidthAvail = 100000;
- else if (ulTemp > 150000) m_ulHighestBandwidthAvail = (UINT32)(ulTemp * 0.90);
- else
- {
- m_ulHighestBandwidthAvail = (UINT32)(ulTemp * 0.85);
- }
- /* Translate the bandwidth from prefs into a starting point */
- if (ulTemp == 14400) m_ulPeakUsedBandwidth = 12240;
- else if (ulTemp == 19200) m_ulPeakUsedBandwidth = 16320;
- else if (ulTemp == 28800) m_ulPeakUsedBandwidth = 24480;
- else if (ulTemp == 33600) m_ulPeakUsedBandwidth = 28560;
- else if (ulTemp == 34400) m_ulPeakUsedBandwidth = 34400;
- else if (ulTemp == 57600) m_ulPeakUsedBandwidth = 51840;
- else if (ulTemp == 65536) m_ulPeakUsedBandwidth = 58980;
- else if (ulTemp == 115200) m_ulPeakUsedBandwidth = 104000;
- else if (ulTemp > 150000) m_ulPeakUsedBandwidth = (UINT32)(ulTemp * 0.91);
- else
- {
- m_ulPeakUsedBandwidth = (UINT32)(ulTemp * 0.90);
- }
- /*
- * Figure out the resistance bitrate for upshifting.
- * Modems get 65k.
- * DSL / Low BW LANs get their pref value.
- * High bandwidth devices cap at 600k
- * (unless the presentation is more)
- */
- if (ulTemp < 65000)
- {
- m_ulResistanceBitRate = 65000;
- }
- else if (ulTemp < 600000)
- {
- m_ulResistanceBitRate = m_ulPeakUsedBandwidth;
- }
- else
- {
- m_ulResistanceBitRate = 600000;
- }
- m_ulOriginalResistanceBitRate = m_ulResistanceBitRate;
- }
- else
- {
- /* Wild Guess */
- m_ulHighestBandwidthAvail = 40000;
- m_ulPeakUsedBandwidth = 40000;
- }
- // LOAD TEST ONLY OPTIONS
- // Read in the preferences for enabling/disabling Accel and
- // Decel for load tests.
- //
- ReadPrefBOOL(pPreferences, "LoadTest", m_bLoadTest);
- ReadPrefBOOL(pPreferences, "DoAccel", m_bDoAccel);
- ReadPrefBOOL(pPreferences, "DoDecel", m_bDoDecel);
- ReadPrefBOOL(pPreferences, "DisableBothAccelDecel", m_bDisableBothAccelDecel);
- ReadPrefFLOAT(pPreferences, "AccelerationFactor", m_fAccelerationFactor);
- // DisableBothAccelDecel override all other preferences.
- // If it is true, set both DoAccel and DoDecel to false.
- // If DisableBothAccelDecel is FALSE do nothing at all.
- if (TRUE == m_bDisableBothAccelDecel)
- {
- m_bDoAccel = FALSE;
- m_bDoDecel = FALSE;
- }
-
- /////////////// END LOAD TEST ONLY SECTION
- /* Get MaxBandwidth from Prefs */
- ReadPrefINT32(pPreferences, "MaxBandwidth", m_ulMaxAccelBitRate);
- HX_RELEASE(pPreferences);
- m_ulOriginalHighestBandwidthAvail = m_ulHighestBandwidthAvail;
- }
- /* This is ONLY used for load testing */
- if (m_bLoadTest)
- {
- const char* pSourceURL = NULL;
- CHXURL* pURL = NULL;
- UINT32 ulTemp = 0;
- IHXValues* pOptions = NULL;
- pSourceURL = pSource->GetURL();
- HX_ASSERT(pSourceURL);
- pURL = new CHXURL(pSourceURL);
- HX_ASSERT(pURL);
- pOptions = pURL->GetOptions();
-
- // Check for the DoAccel and DoDecel URL options. If they are
- // there set the sources properties to reflect them. Also,
- // each option is overriden, in the 'off' state by the global
- // preferences DoAccel and DoDecel. Remember, both the
- // preferences values can be made false by setting the global
- // preference DisableBothAccelDecel to TRUE. Truth Table:
- //
- // Resulting ASM functionality = Option ^ Preference
- //
- // or,
- //
- // m_bSourceAccelAllowed = m_bSourceAccelAllowed^m_bDoAccel
- // m_bSourceDecelAllowed = m_bSourceDecelAllowed^m_bDoDecel
- //
- // Resulting
- // Preferences URL Option String ASM Functionality
- // DoAccel DoDecel DoAccel DoDecel Accel Decel
- // 0 0 0 0 0 0
- // 0 0 0 1 0 0
- // 0 0 1 0 0 0
- // 0 0 1 1 0 0
- // ... ... ... ... ... ...
- // 0 1 0 0 0 0
- // 1 1 1 1 1 1
- // You get the idea. :-)
-
- //First, get any option strings. They default to FALSE in
- //the constructors.
- if( NULL != pOptions )
- {
- if( pOptions->GetPropertyULONG32("DoAccel", ulTemp) == HXR_OK)
- {
- pASMSourceInfo->m_bSourceAccelAllowed = (ulTemp == 1);
- }
- if( pOptions->GetPropertyULONG32("DoDecel", ulTemp) == HXR_OK)
- {
- pASMSourceInfo->m_bSourceDecelAllowed = (ulTemp == 1);
- }
- }//NULL != pOptions
- //Now, do the global preference overrides.
- pASMSourceInfo->m_bSourceAccelAllowed =
- pASMSourceInfo->m_bSourceAccelAllowed && m_bDoAccel;
- pASMSourceInfo->m_bSourceDecelAllowed =
- pASMSourceInfo->m_bSourceDecelAllowed && m_bDoDecel;
- HX_RELEASE(pOptions);
- HX_DELETE(pURL);
- }//m_bLoadTest
- //Report status of load test vars.
- // DEBUG_OUT( m_pEM, DOL_ASM, (s, "LoadTest %d", m_bLoadTest));
- // DEBUG_OUT( m_pEM, DOL_ASM, (s, " DoAccel %u", (UINT16)m_bDoAccel));
- // DEBUG_OUT( m_pEM, DOL_ASM, (s, " DoDecel %u", (UINT16)m_bDoDecel));
- // DEBUG_OUT( m_pEM, DOL_ASM, (s, " DisableBothAccelDecel %d",
- // m_bDisableBothAccelDecel));
- // DEBUG_OUT( m_pEM, DOL_ASM, (s, " m_bSourceAccelAllowed %d",
- // pASMSourceInfo->m_bSourceAccelAllowed));
- // DEBUG_OUT( m_pEM, DOL_ASM, (s, " m_bSourceDecelAllowed %d",
- // pASMSourceInfo->m_bSourceDecelAllowed));
-
- UINT32 unStreamCount = pSource->GetStreamCount();
- pASMSourceInfo->m_pStreams = new ASMStreamInfo*[unStreamCount];;
- BOOL bEnableSDB = FALSE;
- bEnableSDB = (unStreamCount == 0);
- pASMSourceInfo->m_ulLowestBandwidthBeforeTimeStamp = 0;
- for (i = 0; i < unStreamCount; i++)
- {
- IUnknown* pStream = 0;
- IHXStream* pHXStream = NULL;
- ASMStreamInfo* pInfo = new ASMStreamInfo;
- HX_VERIFY(HXR_OK == pSource->GetStream(i, pStream));
- HX_VERIFY(HXR_OK == pStream->QueryInterface
- (IID_IHXStreamBandwidthNegotiator,
- (void **)&pInfo->m_pNegotiator));
- HX_VERIFY(HXR_OK == pStream->QueryInterface
- (IID_IHXStreamBandwidthBias,
- (void **)&pInfo->m_pBias));
- HX_VERIFY(HXR_OK == pStream->QueryInterface
- (IID_IHXAtomicRuleGather,
- (void **)&pInfo->m_pRuleGather));
- pStream->QueryInterface(IID_IHXStream, (void**)&pHXStream);
- if (pHXStream)
- {
- pInfo->m_ulStreamNumber = pHXStream->GetStreamNumber();
- pHXStream->Release();
- }
- pInfo->m_pNegotiator->GetFixedBandwidth(pInfo->m_ulFixedBandwidth);
- if (pInfo->m_ulFixedBandwidth != 1)
- {
- bEnableSDB = TRUE;
- }
- pInfo->m_pASMSourceInfo = pASMSourceInfo;
- pASMSourceInfo->m_pStreams[i] = pInfo;
- m_pASMStreamInfo->AddTail((void *)pInfo);
- 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
- * from our available bandwidth.
- */
- for (j = m_pASMStreamInfo->Begin(); j != m_pASMStreamInfo->End(); ++j)
- {
- INT32 lBias;
- pASMStreamInfo = (ASMStreamInfo*)(*j);
- HX_VERIFY(HXR_OK == pASMStreamInfo->m_pBias->GetBiasFactor(lBias));
- fBiasMean += lBias;
- if (pASMStreamInfo->m_ulFixedBandwidth)
- {
- lAggregateBandwidthUsage -= pASMStreamInfo->m_ulFixedBandwidth;
- ulStreamCount--;
- }
- /* Init this for later */
- pASMStreamInfo->m_ulMasterRuleBookSetOffer = 0;
- }
- /* fBiasMean is not needed if everything has a fixed bandwidth */
- if (ulStreamCount != 0)
- {
- fBiasMean /= (float)ulStreamCount;
- }
- /*
- * Calculate the offer for each source that has a master rulebook
- * defining it's bandwidth division.
- */
- INT32 lNewAggregateBandwidthUsage = lAggregateBandwidthUsage;
- for (j = m_pASMStreamInfo->Begin(); j != m_pASMStreamInfo->End(); ++j)
- {
- INT32 lBias;
- pASMStreamInfo = (ASMStreamInfo*)(*j);
- HX_VERIFY(HXR_OK == pASMStreamInfo->m_pBias->GetBiasFactor(lBias));
- if (pASMStreamInfo->m_pASMSourceInfo->m_pMasterRuleBook)
- {
- UINT32 ulOffer =
- (UINT32)(lAggregateBandwidthUsage / (float)ulStreamCount);
- ulOffer +=
- (UINT32)(((float)lBias - fBiasMean) *
- ((float)lAggregateBandwidthUsage / 100.0) *
- (2.0 / (float)ulStreamCount));
- pASMStreamInfo->m_pASMSourceInfo->m_ulMasterOffer += 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 = (ASMSourceInfo*)(*i);
- ASMRuleBook* pRuleBook = pASMSourceInfo->m_pMasterRuleBook;
- if (pRuleBook)
- {
- UINT32 ulNumStreamsForThisSource =
- pASMSourceInfo->m_pSource->GetStreamCount();
- BOOL* pCurrentSubInfo = new BOOL[pRuleBook->GetNumRules()];
- HXSMUpdateSubscriptionVars(m_pSubscriptionVariables,
- pASMSourceInfo->m_ulMasterOffer,
- 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;
- HX_RESULT hxResult;
-
- // 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
- *
- */
- //If the Stream?Bandwidth property isn't found for
- //all streams don't worry about it. Not all streams
- //may have rule books.
- hxResult = pProps->GetPropertyCString((char *)pTemp, pBw);
- if(HXR_OK==hxResult && pBw)
- {
- pASMSourceInfo->m_pStreams[j]->
- m_ulMasterRuleBookSetOffer =
- atoi((char*)pBw->GetBuffer());
- pBw->Release();
- pBw = NULL;
- }
- else
- {
- pASMSourceInfo
- ->m_pStreams[j]
- ->m_ulMasterRuleBookSetOffer = 0;
- }//HXR_OK==hxResult && pBw
- }
- HX_RELEASE(pProps);
- break;
- }
- }
- delete [] pCurrentSubInfo;
- }
- }
- /*
- * 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 (j = m_pASMStreamInfo->Begin(); j != m_pASMStreamInfo->End(); ++j)
- {
- INT32 lBias;
- pASMStreamInfo = (ASMStreamInfo*)(*j);
- if (pASMStreamInfo->m_ulFixedBandwidth != 0)
- {
- ulTakenBandwidth += pASMStreamInfo->m_ulFixedBandwidth;
- pASMStreamInfo->m_ulResistanceToLower = 0xffffffff;
- continue;
- }
- HX_VERIFY(HXR_OK == pASMStreamInfo->m_pBias->GetBiasFactor(lBias));
- HX_ASSERT(pASMStreamInfo->m_pThreshold != NULL);
- UINT32 ulOffer = 0;
- if (pASMStreamInfo->m_pASMSourceInfo->m_bPerfectPlay)
- {
- UINT32 i = pASMStreamInfo->m_ulMaxEffectiveThreshold;
- ulTakenBandwidth += (UINT32)pASMStreamInfo->m_pThreshold[i];
- pASMStreamInfo->m_ulResistanceToLower = 0xffffffff;
- pASMStreamInfo->m_ulOffer = (UINT32)pASMStreamInfo->m_pThreshold[i];
- pASMStreamInfo->m_ulThresholdPosition = i;
- /*
- * If we are in perfect play mode, just select the highest bandwidth rule
- * and don't negotiate any further.
- */
- continue;
- }
- if (pASMStreamInfo->m_ulMasterRuleBookSetOffer)
- {
- ulOffer = pASMStreamInfo->m_ulMasterRuleBookSetOffer - 1;
- }
- else
- {
- ulOffer =
- (UINT32)(lAggregateBandwidthUsage / (float)ulStreamCount);
- ulOffer +=
- (UINT32)(((float)lBias - fBiasMean) *
- ((float)lAggregateBandwidthUsage / 100.0) *
- (2.0 / (float)ulStreamCount));
- }
- HX_ASSERT(pASMStreamInfo->m_ulMaxEffectiveThreshold >= 0);
- if (pASMStreamInfo->m_ulMaxEffectiveThreshold == 0)
- {
- HX_ASSERT(pASMStreamInfo->m_pThreshold[0] == 0);
- ulTakenBandwidth += (UINT32)pASMStreamInfo->m_pThreshold[0];
- pASMStreamInfo->m_ulResistanceToLower = 0xffffffff;
- }
- else
- {
- for (UINT32 i = 1; i <= pASMStreamInfo->m_ulMaxEffectiveThreshold; i++)
- {
- if ((ulOffer <= pASMStreamInfo->m_pThreshold[i]) ||
- (i == (pASMStreamInfo->m_ulMaxEffectiveThreshold)))
- {
- ulTakenBandwidth += (UINT32)pASMStreamInfo->m_pThreshold[i];
- if (i == 1)
- {
- pASMStreamInfo->m_ulResistanceToLower = 0xffffffff;
- }
- else
- {
- pASMStreamInfo->m_ulResistanceToLower = (ulOffer -
- (UINT32)pASMStreamInfo->m_pThreshold[i - 1]) * ulOffer;
- }
- pASMStreamInfo->
- m_ulOffer = ulOffer;
- pASMStreamInfo->m_ulThresholdPosition = i;
- break;
- }
- }
- }
- }
- lAggregateBandwidthUsage = lCorrectAggregateBandwidthUsage;
- tryagain:
- if (lAggregateBandwidthUsage < (INT32)ulTakenBandwidth)
- {
- /* Resistance is Futile. You will be Real(tm)lyAssimilated */
- UINT32 ulLowestResistance = 0xffffffff;
- ASMStreamInfo* pLowestResistanceStream = 0;
- for (j = m_pASMStreamInfo->Begin(); j != m_pASMStreamInfo->End(); ++j)
- {
- pASMStreamInfo = (ASMStreamInfo*)(*j);
- if (pASMStreamInfo->m_ulResistanceToLower < ulLowestResistance)
- {
- ulLowestResistance = pASMStreamInfo->m_ulResistanceToLower;
- pLowestResistanceStream = pASMStreamInfo;
- }
- }
- if (ulLowestResistance == 0xffffffff)
- {
- }
- else
- {
- ulTakenBandwidth -= (UINT32)
- pLowestResistanceStream->m_pThreshold[pLowestResistanceStream->m_ulThresholdPosition];
- pLowestResistanceStream->m_ulThresholdPosition--;
- ulTakenBandwidth += (UINT32)
- pLowestResistanceStream->m_pThreshold[pLowestResistanceStream->m_ulThresholdPosition];
- if (pLowestResistanceStream->m_ulThresholdPosition == 1)
- {
- pLowestResistanceStream->m_ulResistanceToLower = 0xffffffff;
- }
- else
- {
- pLowestResistanceStream->m_ulResistanceToLower = (pLowestResistanceStream->m_ulOffer -
- (UINT32)pLowestResistanceStream->m_pThreshold[
- pLowestResistanceStream->m_ulThresholdPosition - 1]) *
- pLowestResistanceStream->m_ulOffer;
- }
- goto tryagain;
- }
- }
- UINT32 ulLeftOverForDropByN = lAggregateBandwidthUsage - ulTakenBandwidth;
- BOOL bForce = FALSE;
- for (j = m_pASMStreamInfo->Begin(); j != m_pASMStreamInfo->End(); ++j)
- {
- pASMStreamInfo = (ASMStreamInfo*)(*j);
- UINT32 ulBw = 1;
- if (pASMStreamInfo->m_ulFixedBandwidth)
- {
- ulBw = pASMStreamInfo->m_ulFixedBandwidth;
- }
- else
- {
- ulBw = (UINT32)
- pASMStreamInfo->m_pThreshold[pASMStreamInfo->m_ulThresholdPosition];
- }
- UINT32 ulBwOffered = ulBw;
- if (ulBw == 1)
- {
- // Hack Alert for DropByN. XXXSMP
- ulBwOffered = ulBw = ulLeftOverForDropByN;
- }
- if ((ulBw != pASMStreamInfo->m_ulLastBandwidth) &&
- (!pASMStreamInfo->m_ulFixedBandwidth))
- {
- bForce = TRUE;
- }
- pASMStreamInfo->m_pRuleGather->
- RuleGather(&pASMStreamInfo->m_pASMSourceInfo->
- m_SubscriptionChanges);
- pASMStreamInfo->SetLastBandwidth(ulBw);
- HX_ASSERT(ulBw == ulBwOffered);
- //update the HXASMStream with our new bandwidth
- pASMStreamInfo->NotifyNewBandwidth();
- //update the source's knowledge of tsd
- pASMStreamInfo->NotifyTimeStampDelivery();
- //if the stream is behind, tell the server to chill
- pASMStreamInfo->NotifyLimitBandwidth(ulBwOffered);
- pASMStreamInfo->m_pRuleGather->RuleGather(0);
- }
- for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
- {
- pASMSourceInfo = (ASMSourceInfo*)(*i);
- if (!pASMSourceInfo->m_SubscriptionChanges.IsEmpty())
- {
- pASMSourceInfo->m_pStreams[0]->m_pRuleGather->
- RuleFlush(&pASMSourceInfo->m_SubscriptionChanges);
- for (j = pASMSourceInfo->m_SubscriptionChanges.Begin();
- j != pASMSourceInfo->m_SubscriptionChanges.End(); ++j)
- {
- RTSPSubscription* pSub = (RTSPSubscription*)(*j);
- delete pSub;
- }
- pASMSourceInfo->m_SubscriptionChanges.RemoveAll();
- }
- }
- if (m_State == REDO_ACCEL)
- {
- RecalcAccel();
- return;
- }
- if (m_State == CONGESTION)
- {
- RecalcAccel();
- return;
- }
- if (m_State == INIT)
- {
- m_State = INIT_REDIST;
- RecalcAccel();
- return;
- }
- if (bForce)
- {
- m_State = REDO_ACCEL;
- RecalcAccel();
- return;
- }
- }
- void
- HXSM::RecalcAccel()
- {
- CHXSimpleList::Iterator i, j;
- ASMSourceInfo* pASMSourceInfo;
- ASMStreamInfo* pASMStreamInfo;
- UINT32 ulAggregateUsed = 0;
- UINT32 ulTotalMaxSubscribedBw = 0;
- if (m_State == INIT)
- {
- m_ulOfferToRecalc = m_ulHighestBandwidthAvail;
- if (m_ulOfferToRecalc > m_ulMaxAccelBitRate)
- {
- m_ulOfferToRecalc = m_ulMaxAccelBitRate;
- }
- #ifdef MOREDEBUG
- DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
- "INIT Offer to Recalc() %d", m_ulOfferToRecalc));
- #endif
- Recalc();
- return;
- }
- for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
- {
- pASMSourceInfo = (ASMSourceInfo*)(*i);
- pASMSourceInfo->m_ulSubscribedBw = 0;
- pASMSourceInfo->m_ulMaxSubscribedBw = 0;
- }
- for (j = m_pASMStreamInfo->Begin(); j != m_pASMStreamInfo->End(); ++j)
- {
- pASMStreamInfo = (ASMStreamInfo*)(*j);
- if (pASMStreamInfo->m_ulFixedBandwidth)
- {
- pASMStreamInfo->m_pASMSourceInfo->m_ulSubscribedBw +=
- pASMStreamInfo->m_ulFixedBandwidth;
- pASMStreamInfo->m_pASMSourceInfo->m_ulMaxSubscribedBw +=
- pASMStreamInfo->m_ulFixedBandwidth;
- ulTotalMaxSubscribedBw += pASMStreamInfo->m_ulFixedBandwidth;
- ulAggregateUsed += pASMStreamInfo->m_ulFixedBandwidth;
- }
- else
- {
- pASMStreamInfo->m_pASMSourceInfo->m_ulSubscribedBw += (UINT32)
- pASMStreamInfo->m_pThreshold[
- pASMStreamInfo->m_ulThresholdPosition];
- HX_ASSERT(pASMStreamInfo->m_pASMSourceInfo->m_ulSubscribedBw < 0x7fffffff);
- pASMStreamInfo->m_pASMSourceInfo->m_ulMaxSubscribedBw += (UINT32)
- pASMStreamInfo->m_pThreshold[
- pASMStreamInfo->m_ulMaxEffectiveThreshold];
- ulTotalMaxSubscribedBw += (UINT32)pASMStreamInfo->m_pThreshold[
- pASMStreamInfo->m_ulMaxEffectiveThreshold];
- ulAggregateUsed += (UINT32)
- pASMStreamInfo->m_pThreshold[
- pASMStreamInfo->m_ulThresholdPosition];
- }
- }
- UINT32 ulNumBehindSources = 0;
- UINT32 ulNumSlightlyBehindSources = 0;
- INT32 lAggregateBandwidthUsage = 0;
- INT32 ulMaxNeededBW = 0;
- BOOL bAllZeroBw = TRUE;
- BOOL bFastStart = FALSE;
-
- for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
- {
- pASMSourceInfo = (ASMSourceInfo*)(*i);
- if (pASMSourceInfo->m_ulLastSetDelivery == 0xffffffff)
- {
- pASMSourceInfo->m_ulLastSetDelivery = pASMSourceInfo->m_ulSubscribedBw;
- }
- // if ANY of the sources are fast start then we are in
- // fast start mode. We may wish to re-visit this decision!
- // this comment is for you Rahul!
- if (pASMSourceInfo && pASMSourceInfo->m_pSource)
- {
- bFastStart = bFastStart | pASMSourceInfo->m_pSource->m_bFastStart;
- }
- ulNumBehindSources += pASMSourceInfo->m_bBehind ? 1 : 0;
- ulNumSlightlyBehindSources += pASMSourceInfo->m_bSlightlyBehind ? 1 : 0;
- lAggregateBandwidthUsage += pASMSourceInfo->GetBandwidth();
- if (!pASMSourceInfo->GetBandwidth())
- lAggregateBandwidthUsage += pASMSourceInfo->m_ulSubscribedBw;
- else
- bAllZeroBw = FALSE;
- ulMaxNeededBW += pASMSourceInfo->m_ulMaxSubscribedBw;
- }
- // so if we are in fast start, let's check to see if we don't want to be in
- // fast start!
- double maxPossibleAccelRatio = 0.;
- if (ulMaxNeededBW > 0.)
- {
- maxPossibleAccelRatio = (double) m_ulOriginalHighestBandwidthAvail / (double) ulMaxNeededBW;
- }
- for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
- {
- pASMSourceInfo = (ASMSourceInfo*)(*i);
- // I could check here for pASMSourceInfo->m_pSource->m_bFastStart, but really
- // does it matter?
- if (pASMSourceInfo && pASMSourceInfo->m_pSource)
- {
- pASMSourceInfo->m_pSource->SetMaxPossibleAccelRatio(maxPossibleAccelRatio);
- }
- // turn this stuff of if we are on modem. *sigh* It probably sort of works on
- // modems too. This value makes it work on ISDN, that's ok by me, but if people
- // don't like it, I can change it.
- if (maxPossibleAccelRatio < 1.5 ||
- (m_ulOriginalHighestBandwidthAvail < 110000)) // it now works on DSL or higher
- {
- bFastStart = FALSE;
- if (pASMSourceInfo->m_pSource->m_bFastStart)
- {
- DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,"(%p)ASM %d - Leaving TurboPlay", pASMSourceInfo->m_pSource, __LINE__));
- pASMSourceInfo->m_pSource->LeaveFastStart(TP_OFF_BY_NOTENOUGHBW);
- }
- }
- // Are we currently asking for less than max? Is so Disable!
- //
- // XXX HP I am not sure the following logic is valid, it's possible
- // pASMSourceInfo->m_ulSubscribedBw < pASMSourceInfo->m_ulMaxSubscribedBw because the
- // master rulebook defines so even though we have plenty of bandwidth(i.e. maxPossibleAccelRatio > 1.5)
- // If it's really the case that the source doesn't subscribe to its max. bandwidth because
- // we don't have enough bandwidth, then maxPossibleAccelRatio < 1.5 and we should left faststart
- // already
- /*
- if (pASMSourceInfo && pASMSourceInfo->GetBandwidth() && pASMSourceInfo->m_ulMaxSubscribedBw != pASMSourceInfo->m_ulSubscribedBw
- && pASMSourceInfo->m_pSource->m_bFastStart)
- {
- DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,"ASM %d - Leaving TurboPlay", __LINE__));
- DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,"%d %d %d", pASMSourceInfo->m_ulMaxSubscribedBw, pASMSourceInfo->GetBandwidth(),pASMSourceInfo->m_ulSubscribedBw));
- pASMSourceInfo->m_pSource->LeaveFastStart();
- }
- */
- }
- if (m_bPipeFull == TRUE)
- {
- /*
- * Adjust the highest available bandwidth because we have found
- * the maximum bandwidth that the pipe can handle. We do this
- * so that sources that get added in the future will have
- * some information about the max. bandwidth that exists. This
- * value is aggresive because a source will want to consume everything
- * it can and fall back if it goes over the top.
- */
- HX_ASSERT(lAggregateBandwidthUsage >= 100);
- if (lAggregateBandwidthUsage < 100)
- {
- /*
- * Please have at *least* 100bps before attempting to
- * run the RealPlayer.
- */
- lAggregateBandwidthUsage = 100;
- }
- m_ulHighestBandwidthAvail = (UINT32)(lAggregateBandwidthUsage);
- m_ulPeakUsedBandwidth = (UINT32)(lAggregateBandwidthUsage);
- m_bInitialHighBwAvail = FALSE;
- m_bPipeFull = FALSE;
- }
- if (m_State == REDIST)
- {
- m_State = REDO_ACCEL;
- m_ulOfferToRecalc = m_ulHighestBandwidthAvail;
- Recalc();
- return;
- }
- if ((m_State == REDO_ACCEL) || (m_State == INIT_REDIST))
- {
- UINT32 ulBigValue;
- if ((m_bInitialHighBwAvail) || (m_State == REDO_ACCEL))
- {
- ulBigValue = m_ulPeakUsedBandwidth;
- if (bFastStart && (m_State == INIT_REDIST))
- {
- ulBigValue = m_ulMaxAccelBitRate;
- }
- else if ((INT32)ulBigValue > lAggregateBandwidthUsage)
- {
- ulBigValue = lAggregateBandwidthUsage;
- }
- }
- else
- {
- /*
- * If your state is REDO_ACCEL & we have an imperical value
- * then maybe we should use this (ABU) instead of the above,
- * but this value may not be completely up to date?
- */
- ulBigValue = lAggregateBandwidthUsage;
- }
- HX_ASSERT(ulBigValue > 0); // Rahul's Crazy, This won't ever happen!
- 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)(ulBigValue));
- if ((HXR_OK == pASMSourceInfo->m_pSource->
- QueryInterface(IID_IHXThinnableSource, (void **)&pThin)))
- {
- if ((ulNewValue > (pASMSourceInfo->m_ulLastSetDelivery * 1.02)) ||
- (ulNewValue < (pASMSourceInfo->m_ulLastSetDelivery * 0.98)) ||
- (pASMSourceInfo->m_bAdjustBandwidth && pASMSourceInfo->m_pSource->IsLive()))
- {
- BOOL bFastStart = FALSE;
-
- if (pASMSourceInfo && pASMSourceInfo->m_pSource)
- {
- bFastStart = pASMSourceInfo->m_pSource->m_bFastStart;
- }
- if (bFastStart)
- {
- if (ulNewValue > (pASMSourceInfo->m_ulMaxSubscribedBw * m_fAccelerationFactor))
- {
- ulNewValue = (UINT32)
- (pASMSourceInfo->m_ulMaxSubscribedBw * m_fAccelerationFactor);
- }
-
- // if the server says to cap the value, we cap the value!
- if (pASMSourceInfo && pASMSourceInfo->m_pSource && ulNewValue > pASMSourceInfo->m_pSource->m_ulMaxBandwidth * 1000 )
- {
- ulNewValue = pASMSourceInfo->m_pSource->m_ulMaxBandwidth * 1000;
- }
- // if the value is greater is than the pipe set it to a
- // little less than the pipe!
- if (ulNewValue > m_ulOriginalHighestBandwidthAvail)
- {
- ulNewValue = m_ulOriginalHighestBandwidthAvail;
- }
- }
- else
- {
- 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);
- }
- }
- pASMSourceInfo->m_bAdjustBandwidth = FALSE;
- 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 ((ulNewValue < ulSourceBandwidth) && (ulSourceBandwidth > 10))
- {
- pASMSourceInfo->m_pSource->EnterBufferedPlay();
- }
- if (ulNewValue >= ulSourceBandwidth)
- {
- pASMSourceInfo->m_pSource->LeaveBufferedPlay();
- }
- if ((ulNewValue >= pASMSourceInfo->m_ulLastSetDelivery) &&
- (!pASMSourceInfo->m_bMayBeAccelerated) &&
- (!pASMSourceInfo->m_bTryToUpShift))
- {
- goto dont_actually_set_the_rate;
- }
- if (ulNewValue > m_ulResistanceBitRate && !bFastStart)
- {
- UINT32 ulActualResistanceBitRate = m_ulResistanceBitRate;
- if (ulActualResistanceBitRate < ulAggregateUsed)
- {
- ulActualResistanceBitRate = (UINT32)
- (ulAggregateUsed * 1.05);
- }
- if (ulNewValue > ulActualResistanceBitRate)
- {
- ulNewValue = ulActualResistanceBitRate;
- }
- }
-
- if(pASMSourceInfo->m_bTryToUpShift)
- {
- pASMSourceInfo->m_bTryToUpShift=FALSE;
- //XXXRA why not check for ulNewValue < ((UINT32)(ulSourceBandwidth * 1.15)
- // before assignment.
- ulNewValue = (UINT32)(ulSourceBandwidth * 1.15);
- }
-
- pASMSourceInfo->m_ulLastSetDelivery = 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));
- }
- DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s, "(%p)Redist: Tranmission Rate to %d", pASMSourceInfo->m_pSource, ulActualRate));
- if (m_bEnableSDB)
- {
- pThin->SetDeliveryBandwidth(ulActualRate, 0);
- }
- if (bFastStart)
- {
- pASMSourceInfo->m_pSource->m_turboPlayStats.ulAcceleratedBW = ulActualRate;
- }
- }
- }
- dont_actually_set_the_rate:
- HX_RELEASE(pThin);
- }
- m_State = HX_NONE;
- return;
- }
- if (m_State == CHILL_BUFFERING)
- {
- m_ulOfferToRecalc = lAggregateBandwidthUsage;
- #ifdef MOREDEBUG
- DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
- "CHILL to Recalc() %d", m_ulOfferToRecalc));
- #endif
- m_State = HX_NONE;
- Recalc();
- }
- if ((ulNumBehindSources) ||
- ((lAggregateBandwidthUsage > ((INT32)m_ulMaxAccelBitRate + 100)) &&
- (bAllZeroBw)))
- {
- if ((lAggregateBandwidthUsage > (INT32)m_ulMaxAccelBitRate) &&
- (bAllZeroBw))
- {
- lAggregateBandwidthUsage = m_ulMaxAccelBitRate;
- }
- // XXXRA change m_ulNumReportsSinceUpShift to m_lNumReportsSinceUpShift
- m_ulNumReportsSinceUpShift = -2;
- UINT32 ulLow = (UINT32)(m_ulLastStableBandwidth * 0.90);
- UINT32 ulHigh = (UINT32)(m_ulLastStableBandwidth * 1.10);
- /*
- * XXXSMP Maybe we don't want to use stable point when the aggregate
- * detected is more then the stable point?
- */
- if ((lAggregateBandwidthUsage > (INT32)ulLow) &&
- (lAggregateBandwidthUsage < (INT32)ulHigh))
- {
- /*
- * If we are close to the last stable bandwidth, then let's
- * try that one again.
- */
- lAggregateBandwidthUsage = m_ulLastStableBandwidth;
- #ifdef MOREDEBUG
- DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
- "Used Stable Point %d", m_ulLastStableBandwidth));
- #endif
- m_ulLastStableBandwidth = 0;
- m_ulUpShiftTestPointScaleFactor = MAX(1500,
- (UINT32)(m_ulUpShiftTestPointScaleFactor * 0.85));
- }
- if (m_State != CONGESTION)
- {
- for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
- {
- pASMSourceInfo = (ASMSourceInfo*)(*i);
- UINT32 ulSourceBandwidth = pASMSourceInfo->m_ulSubscribedBw;
- UINT32 ulNewValue =
- (UINT32)(
- (float)ulSourceBandwidth /
- (float)ulAggregateUsed *
- (float)lAggregateBandwidthUsage * 0.97);
- if (ulNewValue < (pASMSourceInfo->m_ulSubscribedBw))
- {
- // Attempt ASM Switching to reduce bandwidth usage.
- m_State = CONGESTION;
- m_ulOfferToRecalc = (UINT32)
- (lAggregateBandwidthUsage * 0.97);
- #ifdef MOREDEBUG
- DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
- "CONGESTION to Recalc() %d", m_ulOfferToRecalc));
- #endif
- // once again, if we are in start start mode we need to
- // turn it off. It may be off already, but I just want to
- // make sure.
- if (pASMSourceInfo->m_pSource->m_bFastStart)
- {
- DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,"(%p)ASM %d - Leaving TurboPlay", pASMSourceInfo->m_pSource, __LINE__));
- pASMSourceInfo->m_pSource->LeaveFastStart(TP_OFF_BY_NETCONGESTION);
- }
- Recalc();
- return;
- }
- }
- m_State = CONGESTION;
- RecalcAccel();
- return;
- } //m_State != CONGESTION
- else
- {
- BOOL bLossBehind = FALSE;
- m_State = HX_NONE;
- UINT32 ulTotalBandwidth = 0;
- 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)lAggregateBandwidthUsage * 0.70);
- if (ulNewValue < ulSourceBandwidth)
- {
- /* Can't be conservative, so go use what we need */
- ulNewValue =
- (UINT32)(
- (float)ulSourceBandwidth /
- (float)ulAggregateUsed *
- (float)lAggregateBandwidthUsage * 0.97);
- // once again, if we are in start start mode we need to
- // turn it off. It may be off already, but I just want to
- // make sure.
- if (pASMSourceInfo->m_pSource->m_bFastStart)
- {
- DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,"(%p)ASM %d - Leaving TurboPlay", pASMSourceInfo->m_pSource, __LINE__));
- pASMSourceInfo->m_pSource->LeaveFastStart(TP_OFF_BY_NETCONGESTION);
- }
- }
- if (pASMSourceInfo->m_bLossBehind &&
- (ulNewValue < ulSourceBandwidth))
- {
- DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
- "(%p)No Loss Reduce: Will Force BP", pASMSourceInfo->m_pSource));
- 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 BwDetectionData[ulReqSize];
- if (!pTemp)
- {
- bOk = FALSE;
- }
- else
- {
- if (m_pBwDetectionData)
- {
- memcpy(pTemp, m_pBwDetectionData, m_ulBwDetectionDataLen * sizeof(BwDetectionData)); /* Flawfinder: ignore */
- HX_VECTOR_DELETE(m_pBwDetectionData);
- }
- m_pBwDetectionData = pTemp;
- m_ulBwDetectionDataLen = ulReqSize;
- }
- }
- return bOk;
- }
- void
- ASMSourceInfo::Done()
- {
- HX_RELEASE(m_pSBI);
- HX_RELEASE(m_pSource);
- m_bIsDone = TRUE;
- }
- STDMETHODIMP_(UINT32)
- ASMSourceInfo::AddRef(void)
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- STDMETHODIMP_(UINT32)
- ASMSourceInfo::Release(void)
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- STDMETHODIMP
- ASMSourceInfo::QueryInterface
- (
- REFIID interfaceID,
- void** ppInterfaceObj
- )
- {
- QInterfaceList qiList[] =
- {
- { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)this },
- { GET_IIDHANDLE(IID_IHXBandwidthManagerInput), (IHXBandwidthManagerInput*)this },
- };
-
- return ::QIFind(qiList, QILISTSIZE(qiList), interfaceID, ppInterfaceObj);
- }
- STDMETHODIMP
- ASMSourceInfo::ReportDataPacket
- (
- UINT32 ulTimeStamp,
- UINT32 ulArrivedTimeStamp,
- UINT32 ulSize
- )
- {
- if (m_bIsDone)
- {
- return HXR_OK;
- }
- UINT32 ulCurrentTime = HX_GET_TICKCOUNT();
- if (!m_pHXASM->m_ulNextPacketWindow)
- {
- m_pHXASM->m_ulNextPacketWindow = ulCurrentTime;
- }
- if (ulSize == REPORT_DATA_PACKET_LOST)
- {
- ULONG32 ulNumLost = ulArrivedTimeStamp-ulTimeStamp+1;
- //XXXgfw Don't allow Decel if this is a load test.....
- if (m_bSourceDecelAllowed)
- {
- m_pHXASM->m_lLoss += ulNumLost;
- }
- m_pHXASM->m_lPacketCounter += ulNumLost;
- return HXR_OK;
- }
- m_pHXASM->m_lPacketCounter++;
- // Make sure we have a buffer for bandwidth detection!
- if (!m_pBwDetectionData)
- {
- //XXXNH: SMP pulled these numbers out of his hat, so let's
- // stick with them for now.
- UINT32 uEstSize = m_TransportType == TNG_TCP ? 300 : 20;
-
- if (!AllocBWDetectionData(uEstSize))
- return HXR_OUTOFMEMORY;
- }
- if (CALCULATE_ELAPSED_TICKS(m_pHXASM->m_ulNextPacketWindow,
- ulCurrentTime) > 3000)
- {
- m_pHXASM->m_ulNextPacketWindow = ulCurrentTime;
- UINT32 ulLossPercentage = (UINT32)(
- 100 * (float)m_pHXASM->m_lLoss / (float)m_pHXASM->m_lPacketCounter);
- #ifdef MOREDEBUG
- DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT, (s, "(%p)Loss %d", m_pSource, ulLossPercentage));
- #endif
- /* Don't do anything unless we have 4% Loss */
- BOOL bDeAccel = (ulLossPercentage >= 4);
- /* Cut down bandwidth usage ONLY if it won't cause a downshift */
- bDeAccel = bDeAccel &&
- (m_ulLastSetDelivery * 0.95 > m_ulSubscribedBw);
- /* Don't throttle back if we're in chill acc buffering */
- bDeAccel = bDeAccel && (m_ulRateBeforeDeAccel == 0);
- /* If Loss is over 20%, always throttle back */
- bDeAccel = bDeAccel || (ulLossPercentage >= 20);
- if (bDeAccel)
- {
- if (ulLossPercentage >= 20)
- {
- /*
- * make sure to never go into timestamp delivery/keyframe mode
- * due to loss
- */
- m_ulIncomingBandwidth = (UINT32) MAX(m_ulLastSetDelivery * 0.85,
- m_ulLowestBandwidthBeforeTimeStamp * 1.05);
- }
- else
- {
- if (ulLossPercentage > 15)
- {
- ulLossPercentage = 15;
- }
-
- // do not change subscription due to "less than 20% loss"
- m_ulIncomingBandwidth = (UINT32) MAX(m_ulLastSetDelivery *
- (1 - (ulLossPercentage / (float)100)),
- m_ulSubscribedBw * 1.05);
- }
- if (m_pSource->m_bFastStart)
- {
- DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT, (s,"(%p)ASM %d - Leaving TurboPlay", m_pSource, __LINE__));
- m_pSource->LeaveFastStart(TP_OFF_BY_NETCONGESTION);
- if (m_ulIncomingBandwidth > m_ulMaxSubscribedBw * 1.05)
- {
- m_ulIncomingBandwidth = m_ulMaxSubscribedBw * 1.05;
- }
- }
- m_bLossBehind = TRUE;
- DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT, (s, "(%p)Lower Loss %d", m_pSource, m_ulIncomingBandwidth));
- /* Signal Recalc to adjust the highest available bandwidth */
- m_pHXASM->m_bPipeFull = TRUE;
- m_bBehind = TRUE;
- m_pHXASM->RecalcAccel();
- m_bBehind = FALSE;
- m_bLossBehind = FALSE;
- }
- else if (ulLossPercentage <= 1)
- {
- m_pHXASM->m_ulUpShiftPastResistanceCount++;
- }
- if (ulLossPercentage > 2)
- {
- m_pHXASM->m_ulUpShiftPastResistanceCount = 0;
- }
- m_pHXASM->m_lLoss = 0;
- m_pHXASM->m_lPacketCounter = 0;
- }
- if (m_bSlidingBwWindowReady)
- {
- //INT32 i;
- UINT32 ulPrevLocation = m_ulSlidingWindowLocation;
- /*
- * Set the data for the current packet
- */
- m_pBwDetectionData[m_ulSlidingWindowLocation].
- m_ulSize = ulSize;
- m_pBwDetectionData[m_ulSlidingWindowLocation].
- m_ulTimeStamp = ulTimeStamp;
- m_pBwDetectionData[m_ulSlidingWindowLocation].
- m_ulATime = ulArrivedTimeStamp;
- m_ulSlidingWindowLocation++;
- /*
- * wrap around if at the end
- */
- if (m_ulSlidingWindowLocation == m_ulBwDetectionDataCount)
- {
- m_ulSlidingWindowLocation = 0;
- }
- /*
- * count up all data for the whole window
- */
- //UINT32 ulWindowSize = 0;
- //for (i = 0; i < m_ulBwDetectionDataCount; i++)
- //{
- // ulWindowSize += m_pBwDetectionData[i].m_ulSize;
- //}
- /*
- * m_ulSlidingWindowLocation now points to the very first
- * info in the window. Take the diff in time from the data
- * that we just entered (ulPrevLocation) and the time of the
- * first data.
- */
- //UINT32 ulWindowRealTime = m_pBwDetectionData[ulPrevLocation].m_ulATime
- // - m_pBwDetectionData[m_ulSlidingWindowLocation].m_ulATime;
- /*
- * Calculate bandwidth for the window in bytes * 8 / millis.
- * I have no idea why it is bytes * 8. //XXXPM?
- * If we are in constant bitrate mode, then this calculated
- * bitrate will be compared to the constant bitrate. If we
- * are not in constant bitrate mode, then this calculated
- * bitrate will be compared to the bitrate coming from the
- * bandwidth reports.
- */
- //m_ulLastBandwidthReport = (UINT32) (ulWindowSize * 8 /
- // ((ulWindowRealTime) / 1000.0));
- // This is the short-term bandwidth count (sans buffering fudge)
- }
- else
- {
- m_pBwDetectionData[m_ulBwDetectionDataCount].
- m_ulSize = ulSize;
- m_pBwDetectionData[m_ulBwDetectionDataCount].
- m_ulTimeStamp = ulTimeStamp;
- m_pBwDetectionData[m_ulBwDetectionDataCount].
- m_ulATime = ulArrivedTimeStamp;
- if(m_TransportType == TNG_TCP)
- {
- if(((m_pBwDetectionData[m_ulBwDetectionDataCount].m_ulTimeStamp -
- m_pBwDetectionData[0].m_ulTimeStamp > 30000) &&
- m_ulBwDetectionDataCount > 300))
- {
- m_bSlidingBwWindowReady = TRUE;
- }
- }
- else if(m_TransportType == TNG_UDP)
- {
- if (((((m_pBwDetectionData[m_ulBwDetectionDataCount].m_ulTimeStamp -
- m_pBwDetectionData[0].m_ulTimeStamp) > 3000) &&
- (m_ulBwDetectionDataCount > 20)) ||
- (m_pBwDetectionData[m_ulBwDetectionDataCount].m_ulATime -
- m_pBwDetectionData[0].m_ulATime > 3000)))
- // XXXSMP Re-examine this formula later.
- {
- m_bSlidingBwWindowReady = TRUE;
- }
- }
- if(!m_bSlidingBwWindowReady)
- {
- m_ulBwDetectionDataCount++;
- // do we not have a big enough buffer for calculating bandwidth?
- if (m_ulBwDetectionDataCount >= m_ulBwDetectionDataLen)
- {
- // if we already have at least 1024 data points or we are
- // out of memory then we'll just have to make do
- UINT32 ulNewSize = m_ulBwDetectionDataLen * 2;
- UINT32 ulMaxSize = min(BW_DETECTION_DATA_POINTS, ulNewSize);
- if (m_ulBwDetectionDataLen >= BW_DETECTION_DATA_POINTS ||
- !AllocBWDetectionData(ulMaxSize))
- {
- m_ulBwDetectionDataCount--;
- m_bSlidingBwWindowReady = TRUE;
- }
- }
- }
- }
- return HXR_OK;
- }
- UINT32
- ASMSourceInfo::GetBandwidthSince(UINT32 ulTime,
- UINT32 ulNow)
- {
- if (m_bIsDone)
- {
- return HXR_OK;
- }
- /*
- * If we have not seen enough yet to get an idea.
- */
- if(!m_bSlidingBwWindowReady)
- {
- //XXXPM Hack this in to make TCP do small window calcs
- if(m_pBwDetectionData && m_TransportType == TNG_TCP &&
- (m_pBwDetectionData[m_ulBwDetectionDataCount].m_ulTimeStamp -
- m_pBwDetectionData[0].m_ulTimeStamp > 1000))
- {
- /* XXXPM, Disgusting */
- goto tcphackedin;
- }
- return 0;
- }
- tcphackedin:
- UINT32 i;
- UINT32 sane = m_ulSlidingWindowLocation;
- UINT32 ulCount = 0;
- if(m_ulSlidingWindowLocation == 0)
- {
- i = m_ulBwDetectionDataCount - 1;
- }
- else
- {
- i = m_ulSlidingWindowLocation - 1;
- }
- UINT32 ulLastTime = ulNow;
- /*
- * add up the data size for all packets since ulTime
- */
- while(m_pBwDetectionData[i].m_ulATime > ulTime)
- {
- ulCount += m_pBwDetectionData[i].m_ulSize;
- /*
- * remember the time of this packet so that we can calculate duration
- */
- ulLastTime = m_pBwDetectionData[i].m_ulATime;
- if(i == 0)
- {
- i = m_ulBwDetectionDataCount - 1;
- }
- else
- {
- i--;
- }
- if(i == sane)
- {
- //XXXPM we have travelled all the way around the window
- //and still don't have enough.
- break;
- }
- }
- if (ulNow == ulLastTime)
- {
- return 0;
- }
- return (UINT32)((ulCount * 8) / ((ulNow - ulLastTime) / 1000.0));
- }
- STDMETHODIMP
- ASMSourceInfo::ReportUpshiftInfo(UINT32 ulTimeStamp,
- UINT32 ulSize)
- {
- // In low heap mode, skip this because it causes the server to alter the
- // transmission rate. NOTE: technically this is the similar change in
- // ReportLatency should disable surestream stream switching, but in
- // testing this is not born out.
- #if defined(HELIX_CONFIG_LOW_HEAP_STREAMING)
- return HXR_OK;
- #endif
- if (m_bIsDone)
- {
- return HXR_OK;
- }
- if (m_TransportType == TNG_TCP)
- return HXR_OK;
- m_pHXASM->UpShiftInfo(ulTimeStamp, ulSize);
- return HXR_OK;
- }
- void
- HXSM::UpShiftInfo(UINT32 ulTimeStamp, UINT32 ulSize)
- {
- UINT32 ulT = 1;
- UINT32 ulS = 0;
- m_ulUpShiftTimes[m_ulUpShiftRingPos] = ulTimeStamp;
- m_ulUpShiftSizes[m_ulUpShiftRingPos] = ulSize;
- m_ulUpShiftRingPos++;
- if (m_ulUpShiftRingPos == 5)
- {
- m_ulUpShiftRingPos = 0;
- m_bUpShiftInfoReady = TRUE;
- }
- if (m_bUpShiftInfoReady)
- {
- for (int i = 0; i < 5; i++)
- {
- /*
- * XXXSMP We should:
- * Weight each BackToBack timing by the size of the packet
- * it timed, because timing larger packets is more accurate.
- */
- ulT += m_ulUpShiftTimes[i];
- ulS += m_ulUpShiftSizes[i];
- }
- }
- if (ulT < 50)
- {
- ulT = (UINT32) (ulT * 1.2); // The clock is not very accurate.
- if (ulT > 50)
- ulT = 50;
- }
- if (m_bUpShiftInfoReady)
- {
- /* Use 5ms padding for good luck */
- m_ulUpShiftBandwidthAvail = ulS * 8000 / (ulT + 5);
- }
- else
- {
- /* Use 40-60ms padding if we are counting on one info item only */
- if (ulSize > 500)
- m_ulUpShiftBandwidthAvail = ulSize * 8000 / (ulTimeStamp + 40);
- else
- m_ulUpShiftBandwidthAvail = ulSize * 8000 / (ulTimeStamp + 60);
- }
- RecalcAccel();
- }
- HX_RESULT
- ASMSourceInfo::ReportLatency(UINT32 ulServerTime,
- UINT32 ulClientTime)
- {
- // In low heap mode, skip this because it causes the server to alter the
- // transmission rate. NOTE: technically this is the similar change in
- // ReportUpShiftInfo should disable surestream stream switching, but in
- // testing this is not born out.
- #if defined(HELIX_CONFIG_LOW_HEAP_STREAMING)
- return HXR_OK;
- #endif
- if (m_bIsDone)
- {
- return HXR_OK;
- }
- INT32 lBackedUp;
- lBackedUp = CalcBackup(ulServerTime, ulClientTime);
- INT32 lDetectedBandwidth;
- if(m_TransportType == TNG_UDP)
- {
- UINT32 ulTemp = MAX(800, 4000 - m_lOuterThreshold);
- UINT32 ulStartWindow = ulClientTime - ulTemp;
- lDetectedBandwidth = GetBandwidthSince(ulStartWindow, ulClientTime);
- }
- else
- {
- lDetectedBandwidth = GetBandwidthSince(ulClientTime -
- TCP_BANDWIDTH_WINDOW, ulClientTime);
- }
- /*
- * The THRESHOLD window is from THRESHOLD to m_lOuterThreshold.
- * Once we go over threshold, we recalc the bandwidth and will do
- * something to slow things down in m_pHXASM->Recalc. We don't
- * want to recalc the bandwidth again until we catch up to THRESHOLD
- * or get slower again. This is so that when we send one LimitBandwidth
- * message we don't send another just when we are catching up (because
- * sometimes during this time we can receive less and less data.)
- */
- //XXXgfw Don't allow Decel if this is a load test.....
- if ((lBackedUp >= (INT32)THRESHOLD) && (m_bSourceDecelAllowed))
- {
- /*
- * If we are backed up over our threshold window, then resize the
- * window and recalc our bandwidth.
- */
- if ((lBackedUp > m_lOuterThreshold) &&
- ((lDetectedBandwidth < (INT32)m_ulIncomingBandwidth) ||
- (!m_ulIncomingBandwidth)))
- {
- m_ulIncomingBandwidth = lDetectedBandwidth;
- /* Signal Recalc to adjust the highest available bandwidth */
- m_pHXASM->m_bPipeFull = TRUE;
- m_lOuterThreshold = lBackedUp + 500;
- }
- /*
- * This can either grow or shrink the threshold window.
- */
- m_bBehind = TRUE;
- m_bSlightlyBehind = TRUE;
- }
- else
- {
- m_lOuterThreshold = THRESHOLD;
- m_bBehind = FALSE;
- UINT ulNew = 0;
- //XXXgfw Don't allow Decel if this is a load test.....
- if ((lBackedUp > 400) && (m_bSourceDecelAllowed))
- m_bSlightlyBehind = TRUE;
- else
- {
- m_bSlightlyBehind = FALSE;
- if (m_TransportType == TNG_TCP)
- {
- DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT,
- (s, "(%p)TCP Shift up = %d", m_pSource,
- m_pHXASM->m_ulUpShiftBandwidthAvail));
- m_pHXASM->m_ulUpShiftBandwidthAvail = MAX(
- m_pHXASM->m_ulUpShiftBandwidthAvail,
- (UINT32)(lDetectedBandwidth * 1.5));
- }
- }
- if (m_bInvalidUpReport)
- {
- m_bInvalidUpReport = FALSE;
- m_ulLastReportTime = ulClientTime;
- return HXR_OK;
- }
- UINT32 ulTemp = MAX(m_ulRateBeforeDeAccel, m_ulLastSetDelivery);
- if ((lDetectedBandwidth > (INT32)ulTemp) ||
- (!m_ulIncomingBandwidth))
- ulNew = ulTemp + 1;
- else
- ulNew = lDetectedBandwidth;
- if (ulNew > m_ulIncomingBandwidth)
- {
- m_ulIncomingBandwidth = ulNew;
- }
- }
- m_ulLastReportTime = ulClientTime;
- m_pHXASM->m_ulNumReportsSinceUpShift++;
- if (m_bPendingChill)
- {
- m_bPendingChill = FALSE;
- m_pHXASM->m_State = HXSM::CHILL_BUFFERING;
- m_pHXASM->RecalcAccel();
- IHXThinnableSource* pThin = NULL;
- if ((HXR_OK == m_pSource->
- QueryInterface(IID_IHXThinnableSource, (void **)&pThin)))
- {
- HX_ASSERT(m_ulSubscribedBw > 0);
- m_ulRateBeforeDeAccel = m_ulLastSetDelivery;
- UINT32 ulSet;
- if (m_ulIncomingBandwidth > m_ulMaxSubscribedBw)
- {
- ulSet = m_ulMaxSubscribedBw;
- }
- else
- {
- ulSet = (UINT32)(m_ulSubscribedBw * 0.75);
- }
- DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT,
- (s, "(%p)Acceleration Buffer Full: NewTransmissionRate=%d %p", m_pSource,
- ulSet, this));
- pThin->SetDeliveryBandwidth((m_ulLastSetDelivery = ulSet), 0);
- }
- HX_RELEASE(pThin);
- }
- else
- m_pHXASM->RecalcAccel();
- return HXR_OK;
- }
- INT32
- ASMSourceInfo::CalcBackup(UINT32 ulServerTime, UINT32 ulClientTime)
- {
- INT32 lNewDiff = ulClientTime - ulServerTime;
- /*
- * If this is the first time we will have no idea of the base
- * time diff.
- */
- if(!m_lTimeDiffBase)
- {
- m_lTimeDiffBase = lNewDiff;
- return 0;
- }
- /*
- * If our difference got shorter than before then this is the new base
- * and our backup is 0
- */
- if(lNewDiff < m_lTimeDiffBase)
- {
- m_lTimeDiffBase = lNewDiff;
- return 0;
- }
- if (m_lLastBehindTime)
- {
- if (((INT32)m_ulBytesBehind +
- ((lNewDiff - m_lTimeDiffBase) - m_lLastBehindTime) *
- (INT32)m_ulLastSetDelivery / 8000) > 0)
- {
- m_ulBytesBehind +=
- ((lNewDiff - m_lTimeDiffBase) - m_lLastBehindTime) *
- (INT32)m_ulLastSetDelivery / 8000;
- }
- else
- {
- m_ulBytesBehind = 0;
- }
- }
- m_lLastBehindTime = lNewDiff - m_lTimeDiffBase;
- DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT_EXTENDED,
- (s, "(%p)Terminal Buffer Report: Behind by %dms (%d bytes)", m_pSource,
- lNewDiff - m_lTimeDiffBase, m_ulBytesBehind));
- return lNewDiff - m_lTimeDiffBase;
- }
- STDMETHODIMP
- ASMSourceInfo::SetCongestionFactor(UINT32 ulFactor)
- {
- if (m_bIsDone)
- {
- return HXR_OK;
- }
- return HXR_OK;
- }
- void
- ASMSourceInfo::ChangeAccelerationStatus(BOOL bMayBeAccelerated,
- BOOL bUseAccelerationFactor,
- UINT32 ulAccelerationFactor)
- {
- if (m_bMayBeAccelerated == FALSE && bMayBeAccelerated == FALSE)
- {
- DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT,
- (s, "(%p)Acceleration Buffer Way Full: Factor=%d", m_pSource, ulAccelerationFactor));
- HX_ASSERT(bUseAccelerationFactor);
- UINT32 ulNewRate = m_ulSubscribedBw * ulAccelerationFactor / 100;
- IHXThinnableSource* pThin = NULL;
- if (HXR_OK == m_pSource->
- QueryInterface(IID_IHXThinnableSource, (void **)&pThin))
- {
- pThin->SetDeliveryBandwidth((m_ulLastSetDelivery = ulNewRate), 0);
- }
- HX_RELEASE(pThin);
- return;
- }
- m_bMayBeAccelerated = bMayBeAccelerated;
- if (!m_bMayBeAccelerated && (m_ulLastSetDelivery > m_ulSubscribedBw))
- {
- m_bPendingChill = TRUE;
- }
- else if (m_bMayBeAccelerated && m_ulRateBeforeDeAccel)
- {
- IHXThinnableSource* pThin = NULL;
- if (HXR_OK == m_pSource->
- QueryInterface(IID_IHXThinnableSource, (void **)&pThin))
- {
- /* Only attempt conservative restart on LBR sources */
- if (m_ulRateBeforeDeAccel < 150000)
- {
- /* Can we be conservative when switching back up? */
- if ((m_ulRateBeforeDeAccel * 0.50) > m_ulSubscribedBw)
- {
- /* Yes, be really conservative */
- m_ulRateBeforeDeAccel = (UINT32)
- (m_ulRateBeforeDeAccel * 0.70);
- }
- else if ((m_ulRateBeforeDeAccel * 0.70) > m_ulSubscribedBw)
- {
- /* Be somewhat conservative */
- m_ulRateBeforeDeAccel = (UINT32)
- (m_ulRateBeforeDeAccel * 0.85);
- }
- }
- DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT,
- (s, "(%p)Acceleration Buffer at 50%: NewTransmissionRate=%d", m_pSource, m_ulRateBeforeDeAccel));
- pThin->SetDeliveryBandwidth(
- (m_ulLastSetDelivery = (UINT32) (m_ulRateBeforeDeAccel)), 0);
- m_ulRateBeforeDeAccel = 0;
- }
- HX_RELEASE(pThin);
- }
- }
- STDMETHODIMP
- ASMSourceInfo::SetTransportType(TRANSPORT_TYPE type)
- {
- if (m_bIsDone)
- {
- return HXR_OK;
- }
- m_TransportType = type;
- if (m_TransportType == TNG_TCP)
- {
- THRESHOLD = 5000;
- m_lOuterThreshold = 5000;
- }
- return HXR_OK;
- }
- ASMStreamInfo::ASMStreamInfo() :
- m_pNegotiator(0),
- m_pBias(0),
- m_pRuleGather(0),
- m_ulFixedBandwidth(0),
- m_ulLastBandwidth(0),
- m_bTimeStampDelivery(FALSE),
- m_ulNumThresholds(0),
- m_ulThresholdPosition(0),
- m_ulResistanceToLower(0),
- m_ulOffer(0),
- m_pThreshold(NULL),
- m_ulMaxEffectiveThreshold(-1),
- m_ulStreamNumber(0)
- {
- }
- ASMStreamInfo::~ASMStreamInfo()
- {
- HX_VECTOR_DELETE(m_pThreshold);
- HX_RELEASE(m_pNegotiator);
- HX_RELEASE(m_pBias);
- HX_RELEASE(m_pRuleGather);
- }