hxsm.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:84k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: hxsm.cpp,v 1.17.2.1 2004/07/09 02:05:30 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. /*
  50.  *  
  51.  *  ASM Manager for all streams in all Players.
  52.  *
  53.  *  This class will manage the bandwidth requirements
  54.  *  of multiple streams.
  55.  */
  56. #include "hlxclib/stdio.h"      /* printf */
  57. #include "hlxclib/stdlib.h"     /* atoi on Mac */
  58. #include "hxtypes.h"    /* Basic Types */
  59. #include "hxcom.h"      /* IUnknown */
  60. #include "hxslist.h"
  61. #include "hxerror.h"
  62. #include "hxsmbw.h"
  63. #include "hxsm.h"      /* HXSM */
  64. #include "hxsmutil.h"
  65. #include "hxpref.h"
  66. #include "ihxpckts.h"
  67. #include "hxcore.h"
  68. #include "asmrulep.h"
  69. #include "hxbuffer.h"
  70. #include "chxpckts.h"
  71. #include "hxbsrc.h"
  72. #include "hxsrc.h"
  73. #include "errdbg.h"
  74. #include "rtspif.h"
  75. #include "hxurl.h"
  76. #include "hxtick.h"
  77. #include "hxstrutl.h"
  78. #include "hxbufctl.h"
  79. #include "hxheap.h"
  80. #ifdef _DEBUG
  81. #undef HX_THIS_FILE
  82. static const char HX_THIS_FILE[] = __FILE__;
  83. #endif
  84. #ifndef MIN
  85. #define MIN(x, y) (((x) < (y)) ? (x) : (y))
  86. #endif
  87. #ifndef MAX
  88. #define MAX(x, y) (((x) > (y)) ? (x) : (y))
  89. #endif
  90. HXSM::HXSM()
  91.     : m_State(HX_NONE)
  92.     , m_lRefCount(0)
  93.     , m_pSubscriptionVariables(0)
  94.     , m_ulOriginalHighestBandwidthAvail(0)
  95.     , m_ulHighestBandwidthAvail(0)
  96.     , m_ulPeakUsedBandwidth(0)
  97.     , m_ulUpShiftRingPos(0)
  98.     , m_ulUpShiftBandwidthAvail(0)
  99.     , m_ulNumSources(0)
  100.     , m_ulMaxAccelBitRate(0xffffffff)
  101.     , m_ulNumReportsSinceUpShift(2)
  102.     , m_ulLastStableBandwidth(0)
  103.     , m_ulUpShiftTestPointScaleFactor(4000)
  104.     , m_ulOfferToRecalc(0)
  105.     , m_ulNextPacketWindow(0)
  106.     , m_lPacketCounter(0)
  107.     , m_ulUpShiftPastResistanceCount(0)
  108.     , m_lLoss(0)
  109.     , m_bInitialHighBwAvail(TRUE)
  110.     , m_bPipeFull(FALSE)
  111.     , m_bUpShiftInfoReady(FALSE)
  112.     , m_bDidOfferUpShiftToRecalc(FALSE)
  113.     , m_bLoadTest(FALSE)
  114.     , m_bDoAccel(TRUE)
  115.     , m_bDoDecel(TRUE)
  116.     , m_bDisableBothAccelDecel(FALSE)
  117.     , m_fAccelerationFactor(4.0)
  118.     , m_bEnableSDB(TRUE)
  119. #ifndef GOLD
  120.     , m_pEM(0)
  121. #endif
  122. {
  123.     m_pASMSourceInfo = new CHXSimpleList;
  124.     m_pASMStreamInfo = new CHXSimpleList;
  125. }
  126. HXSM::~HXSM()
  127. {
  128. #ifndef GOLD
  129.     HX_RELEASE(m_pEM);
  130. #endif
  131.     CHXSimpleList::Iterator     i;
  132.     ASMSourceInfo*                 pASMSourceInfo;
  133.     ASMStreamInfo*                 pASMStreamInfo;
  134.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  135.     {
  136. pASMSourceInfo = (ASMSourceInfo*)(*i);
  137. pASMSourceInfo->Release();
  138.     }
  139.     for (i = m_pASMStreamInfo->Begin(); i != m_pASMStreamInfo->End(); ++i)
  140.     {
  141. pASMStreamInfo = (ASMStreamInfo*)(*i);
  142. delete pASMStreamInfo;
  143.     }
  144.     delete m_pASMSourceInfo;
  145.     delete m_pASMStreamInfo;
  146.     HX_RELEASE(m_pSubscriptionVariables);
  147. }
  148. STDMETHODIMP_(UINT32)
  149. HXSM::AddRef(void)
  150. {
  151.     return InterlockedIncrement(&m_lRefCount);
  152. }
  153. STDMETHODIMP_(UINT32)
  154. HXSM::Release(void)
  155. {
  156.     if (InterlockedDecrement(&m_lRefCount) > 0)
  157.     {
  158. return m_lRefCount;
  159.     }
  160.     delete this;
  161.     return 0;
  162. }
  163. STDMETHODIMP
  164. HXSM::QueryInterface
  165. (
  166.     REFIID interfaceID,
  167.     void** ppInterfaceObj
  168. )
  169. {
  170.     QInterfaceList qiList[] =
  171.         {
  172.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)this },
  173.             { GET_IIDHANDLE(IID_IHXBandwidthManager), (IHXBandwidthManager*)this },
  174.         };
  175.     
  176.     return ::QIFind(qiList, QILISTSIZE(qiList), interfaceID, ppInterfaceObj);
  177. }
  178. STDMETHODIMP
  179. HXSM::RegisterSource(HXSource* pSource, IUnknown* pUnknown)
  180. {
  181.     IHXSourceBandwidthInfo* pSBI;
  182.     IHXPreferences* pPreferences = NULL;
  183.     ASMSourceInfo* pASMSourceInfo = NULL;
  184.     UINT16 i;
  185. #ifndef GOLD
  186.     HX_RELEASE(m_pEM);
  187.     pUnknown->QueryInterface(IID_IHXErrorMessages, (void **)&m_pEM);
  188. #endif
  189.     DEBUG_OUT(m_pEM, DOL_BWMGR, (s, "Register Source %p %s", pSource, pSource->GetURL()));
  190.     if (HXR_OK == pSource->QueryInterface(IID_IHXSourceBandwidthInfo, 
  191.     (void **)&pSBI))
  192.     {
  193. pASMSourceInfo = new ASMSourceInfo(pSource, this);
  194. pASMSourceInfo->AddRef();
  195. pASMSourceInfo->m_pSBI = pSBI;
  196. /* Local source is always considered in perfect play mode UNLESS we are
  197.  * in simulated network playback mode (used Preview mode in the Encoder)
  198.  */
  199. pASMSourceInfo->m_bPerfectPlay = pSource->IsPerfectPlay() && !pSource->IsSimulatedNetworkPlayback();
  200. m_ulNumSources++;
  201. m_pASMSourceInfo->AddTail((void *)pASMSourceInfo);
  202. pSBI->InitBw(pASMSourceInfo);
  203.     }
  204.     else
  205.     {
  206. return HXR_OK;
  207.     }
  208.     /*
  209.      * This variable tells us the highest amount of bandwidth that we
  210.      * believe is useable.  If we stream thin, then the highest value
  211.      * that the pipe can support would be the aggregate bandwidth of
  212.      * the sources.  Barring any thinning, this would be the bandwidth
  213.      * from prefs (unless we can determine it through fast buffering or
  214.      * another transport feature).  This value is used when starting sources
  215.      * as a initial guess for bandwidth (to set subscriptions).
  216.      */
  217.     if (m_ulHighestBandwidthAvail == 0)
  218.     {
  219. pUnknown->QueryInterface(IID_IHXPreferences, (void **)&pPreferences);
  220.         UINT32 ulTemp = 0;
  221. /* Get initial bandwidth guess from Prefs */
  222.         if (HXR_OK == ReadPrefINT32(pPreferences, "Bandwidth", ulTemp))
  223.         {
  224.     m_bInitialHighBwAvail = TRUE;
  225.     /* Translate the bandwidth from prefs into a starting point */
  226.          if (ulTemp == 14400)    m_ulHighestBandwidthAvail = 11000;
  227.     else if (ulTemp == 19200)    m_ulHighestBandwidthAvail = 14400;
  228.     else if (ulTemp == 28800)    m_ulHighestBandwidthAvail = 21600;
  229.     else if (ulTemp == 33600)    m_ulHighestBandwidthAvail = 25000;
  230.     else if (ulTemp == 34400)    m_ulHighestBandwidthAvail = 34400;
  231.     else if (ulTemp == 57600)    m_ulHighestBandwidthAvail = 50000;
  232.     else if (ulTemp == 65536)  m_ulHighestBandwidthAvail = 56360;
  233.     else if (ulTemp == 115200)   m_ulHighestBandwidthAvail = 100000;
  234.     else if (ulTemp >  150000)   m_ulHighestBandwidthAvail = (UINT32)(ulTemp * 0.90);
  235.     else
  236.     {
  237. m_ulHighestBandwidthAvail = (UINT32)(ulTemp * 0.85);
  238.     }
  239.     /* Translate the bandwidth from prefs into a starting point */
  240.          if (ulTemp == 14400)    m_ulPeakUsedBandwidth = 12240;
  241.     else if (ulTemp == 19200)    m_ulPeakUsedBandwidth = 16320;
  242.     else if (ulTemp == 28800)    m_ulPeakUsedBandwidth = 24480;
  243.     else if (ulTemp == 33600)    m_ulPeakUsedBandwidth = 28560;
  244.     else if (ulTemp == 34400)    m_ulPeakUsedBandwidth = 34400;
  245.     else if (ulTemp == 57600)    m_ulPeakUsedBandwidth = 51840;
  246.     else if (ulTemp == 65536)  m_ulPeakUsedBandwidth = 58980;
  247.     else if (ulTemp == 115200)   m_ulPeakUsedBandwidth = 104000;
  248.     else if (ulTemp >  150000)   m_ulPeakUsedBandwidth = (UINT32)(ulTemp * 0.91);
  249.     else
  250.     {
  251. m_ulPeakUsedBandwidth = (UINT32)(ulTemp * 0.90);
  252.     }
  253.     /*
  254.      * Figure out the resistance bitrate for upshifting.
  255.      * Modems get 65k.
  256.      * DSL / Low BW LANs get their pref value.
  257.      * High bandwidth devices cap at 600k
  258.      *    (unless the presentation is more)
  259.      */
  260.     if (ulTemp < 65000)
  261.     {
  262. m_ulResistanceBitRate = 65000;
  263.     }
  264.     else if (ulTemp < 600000)
  265.     {
  266. m_ulResistanceBitRate = m_ulPeakUsedBandwidth;
  267.     }
  268.     else
  269.     {
  270. m_ulResistanceBitRate = 600000;
  271.     }
  272.     m_ulOriginalResistanceBitRate = m_ulResistanceBitRate;
  273. }
  274. else
  275. {
  276.     /* Wild Guess */
  277.     m_ulHighestBandwidthAvail = 40000;
  278.     m_ulPeakUsedBandwidth = 40000;
  279. }
  280. //        LOAD TEST ONLY OPTIONS
  281. // Read in the preferences for enabling/disabling Accel and 
  282. // Decel for load tests.
  283. //
  284.         ReadPrefBOOL(pPreferences, "LoadTest", m_bLoadTest);
  285.         ReadPrefBOOL(pPreferences, "DoAccel", m_bDoAccel);
  286.         ReadPrefBOOL(pPreferences, "DoDecel", m_bDoDecel);
  287.         ReadPrefBOOL(pPreferences, "DisableBothAccelDecel", m_bDisableBothAccelDecel);
  288.         ReadPrefFLOAT(pPreferences, "AccelerationFactor", m_fAccelerationFactor);
  289. // DisableBothAccelDecel override all other preferences.
  290. // If it is true, set both DoAccel and DoDecel to false.
  291. // If DisableBothAccelDecel is FALSE do nothing at all.
  292. if (TRUE == m_bDisableBothAccelDecel)
  293. {
  294.     m_bDoAccel = FALSE;
  295.     m_bDoDecel = FALSE;
  296. }
  297. /////////////// END LOAD TEST ONLY SECTION
  298. /* Get MaxBandwidth from Prefs */
  299.         ReadPrefINT32(pPreferences, "MaxBandwidth", m_ulMaxAccelBitRate); 
  300. HX_RELEASE(pPreferences);
  301. m_ulOriginalHighestBandwidthAvail = m_ulHighestBandwidthAvail;
  302.     }
  303.     /* This is ONLY used for load testing */
  304.     if (m_bLoadTest)
  305.     {
  306. const char* pSourceURL        = NULL;
  307. CHXURL*     pURL        = NULL;
  308. UINT32     ulTemp        = 0;
  309. IHXValues*  pOptions        = NULL;
  310. pSourceURL = pSource->GetURL();
  311. HX_ASSERT(pSourceURL);
  312. pURL = new CHXURL(pSourceURL);
  313. HX_ASSERT(pURL);
  314. pOptions = pURL->GetOptions();
  315. // Check for the DoAccel and DoDecel URL options. If they are
  316. // there set the sources properties to reflect them.  Also,
  317. // each option is overriden, in the 'off' state by the global
  318. // preferences DoAccel and DoDecel. Remember, both the
  319. // preferences values can be made false by setting the global
  320. // preference DisableBothAccelDecel to TRUE. Truth Table:
  321. //
  322. // Resulting ASM functionality = Option ^ Preference
  323. //
  324. // or,
  325. //
  326. // m_bSourceAccelAllowed = m_bSourceAccelAllowed^m_bDoAccel
  327. // m_bSourceDecelAllowed = m_bSourceDecelAllowed^m_bDoDecel
  328. //
  329. //                                           Resulting
  330. //   Preferences     URL Option String   ASM Functionality
  331. // DoAccel  DoDecel   DoAccel  DoDecel    Accel   Decel
  332. //   0        0         0        0          0       0
  333. //   0        0         0        1          0       0
  334. //   0        0         1        0          0       0
  335. //   0        0         1        1          0       0
  336. //   ...      ...       ...      ...        ...     ...
  337. //   0        1         0        0          0       0
  338. //   1        1         1        1          1       1
  339. // You get the idea. :-)
  340. //First, get any option strings. They default to FALSE in
  341. //the constructors.
  342. if( NULL != pOptions )
  343. {
  344.     if( pOptions->GetPropertyULONG32("DoAccel", ulTemp) == HXR_OK)
  345.     {
  346. pASMSourceInfo->m_bSourceAccelAllowed = (ulTemp == 1);
  347.     }
  348.     if( pOptions->GetPropertyULONG32("DoDecel", ulTemp) == HXR_OK)
  349.     {
  350. pASMSourceInfo->m_bSourceDecelAllowed = (ulTemp == 1);
  351.     }
  352. }//NULL != pOptions
  353. //Now, do the global preference overrides.
  354. pASMSourceInfo->m_bSourceAccelAllowed =
  355.     pASMSourceInfo->m_bSourceAccelAllowed && m_bDoAccel;
  356. pASMSourceInfo->m_bSourceDecelAllowed =
  357.     pASMSourceInfo->m_bSourceDecelAllowed && m_bDoDecel;
  358. HX_RELEASE(pOptions);
  359. HX_DELETE(pURL);
  360.     }//m_bLoadTest
  361.     //Report status of load test vars.
  362. //      DEBUG_OUT( m_pEM, DOL_ASM, (s, "LoadTest %d", m_bLoadTest));
  363. //      DEBUG_OUT( m_pEM, DOL_ASM, (s, "    DoAccel %u",  (UINT16)m_bDoAccel));
  364. //      DEBUG_OUT( m_pEM, DOL_ASM, (s, "    DoDecel %u", (UINT16)m_bDoDecel));
  365. //      DEBUG_OUT( m_pEM, DOL_ASM, (s, "    DisableBothAccelDecel %d",
  366. //   m_bDisableBothAccelDecel));
  367. //      DEBUG_OUT( m_pEM, DOL_ASM, (s, "    m_bSourceAccelAllowed %d",
  368. //       pASMSourceInfo->m_bSourceAccelAllowed));
  369. //      DEBUG_OUT( m_pEM, DOL_ASM, (s, "    m_bSourceDecelAllowed %d",
  370. //   pASMSourceInfo->m_bSourceDecelAllowed));
  371.     
  372.     UINT32 unStreamCount = pSource->GetStreamCount();     
  373.     pASMSourceInfo->m_pStreams = new ASMStreamInfo*[unStreamCount];;
  374.     BOOL bEnableSDB = FALSE;
  375.     bEnableSDB = (unStreamCount == 0);
  376.     pASMSourceInfo->m_ulLowestBandwidthBeforeTimeStamp = 0;
  377.     for (i = 0; i < unStreamCount; i++)
  378.     {
  379. IUnknown* pStream = 0;
  380.         IHXStream* pHXStream = NULL;
  381. ASMStreamInfo* pInfo = new ASMStreamInfo;
  382. HX_VERIFY(HXR_OK == pSource->GetStream(i, pStream));
  383. HX_VERIFY(HXR_OK == pStream->QueryInterface
  384.     (IID_IHXStreamBandwidthNegotiator,
  385.     (void **)&pInfo->m_pNegotiator));
  386. HX_VERIFY(HXR_OK == pStream->QueryInterface
  387.     (IID_IHXStreamBandwidthBias,
  388.     (void **)&pInfo->m_pBias));
  389. HX_VERIFY(HXR_OK == pStream->QueryInterface
  390.     (IID_IHXAtomicRuleGather,
  391.     (void **)&pInfo->m_pRuleGather));
  392.         pStream->QueryInterface(IID_IHXStream, (void**)&pHXStream);
  393.         if (pHXStream)
  394.         {
  395.             pInfo->m_ulStreamNumber = pHXStream->GetStreamNumber();
  396.             pHXStream->Release();
  397.         }
  398. pInfo->m_pNegotiator->GetFixedBandwidth(pInfo->m_ulFixedBandwidth);
  399.         if (pInfo->m_ulFixedBandwidth != 1)
  400.         {
  401.             bEnableSDB = TRUE;
  402.         }
  403. pInfo->m_pASMSourceInfo = pASMSourceInfo;
  404. pASMSourceInfo->m_pStreams[i] = pInfo;
  405. m_pASMStreamInfo->AddTail((void *)pInfo);
  406. UINT32 ulLowestBandwidthBeforeTimeStamp = 0;
  407. if (pInfo->m_ulFixedBandwidth != 0)
  408. {
  409.     ulLowestBandwidthBeforeTimeStamp = pInfo->m_ulFixedBandwidth;
  410. }
  411. else
  412. {
  413.     // XXXNH: 6/7/99
  414.     // We make this threshold array once and create it to be as large
  415.     // as we will ever possibly need.  Each subsequent call to
  416.     // GetThresholdInfo() should never need more than GetNumThresholds
  417.     // returns.  UNLESS the ASMStreamInfo's m_pNegotiator were to 
  418.     // change, but I don't think that's a feature we support.
  419.     UINT32 ulNumThresholds = 
  420. pInfo->m_pNegotiator->GetNumThresholds();
  421.     pInfo->m_pThreshold = new float[ulNumThresholds];
  422.     pInfo->m_pNegotiator->GetThresholdInfo(
  423. (float*)pInfo->m_pThreshold, 
  424. pInfo->m_ulNumThresholds);
  425.     pInfo->m_ulMaxEffectiveThreshold = pInfo->m_ulNumThresholds - 1;
  426.     ulNumThresholds = pInfo->m_ulNumThresholds;
  427.     ulLowestBandwidthBeforeTimeStamp = (UINT32) pInfo->m_pThreshold[ulNumThresholds-1];
  428.     for (UINT32 i = ulNumThresholds-1; i > 0 ; i--)
  429.     {
  430. UINT32 ulCurBand = (UINT32) pInfo->m_pThreshold[i];
  431. // used for timestamp rules
  432. if (ulCurBand == 0 || ulCurBand == 1)
  433. {
  434.     break;
  435. }
  436. else 
  437. {
  438.     ulLowestBandwidthBeforeTimeStamp = ulCurBand;
  439. }
  440.     }
  441. }
  442. HX_ASSERT(ulLowestBandwidthBeforeTimeStamp != 0);
  443. pASMSourceInfo->m_ulLowestBandwidthBeforeTimeStamp += ulLowestBandwidthBeforeTimeStamp;
  444. HX_RELEASE(pStream);
  445.     }
  446.     // Rule for determining if SetDeliveryBandwidth is used.
  447.     //
  448.     // HXASMStream::bFixed   bEnabledSDB  m_bEnableSDB
  449.     // ------------------------------------------
  450.     //     FALSE             FALSE       TRUE  // no fbw means bw > 1
  451.     //     FALSE             TRUE        TRUE  // at least one rule is fbw==1
  452.     //     TRUE              FALSE       FALSE // all bw are fbw==1
  453.     //     TRUE              TRUE        TRUE  // no streamcount, SDB true
  454.     m_bEnableSDB = bEnableSDB;
  455.     return HXR_OK;
  456. }
  457. STDMETHODIMP
  458. HXSM::RegisterSourcesDone()
  459. {
  460.     if (m_pASMSourceInfo->GetCount() > 0 &&
  461. m_pASMStreamInfo->GetCount() > 0)
  462.     {
  463.         CHXSimpleList::Iterator     i;
  464.         ASMSourceInfo*     pASMSourceInfo;
  465.         for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  466.         {
  467.     pASMSourceInfo = (ASMSourceInfo*)(*i);
  468.             if (pASMSourceInfo && pASMSourceInfo->m_pSource)
  469.             {
  470.         DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s, "(%p)RegisterSourcesDone AccelFactor:%f", pASMSourceInfo->m_pSource, m_fAccelerationFactor));
  471.                 if (pASMSourceInfo->m_pSource->m_bFastStart)
  472.                 {
  473.                      pASMSourceInfo->m_ulLastSetDelivery = 0;
  474.                 }
  475.             }
  476.         }
  477. m_State = INIT;
  478. RecalcAccel();
  479.     }
  480.     return HXR_OK;    
  481. }
  482. BOOL
  483. HXSM::NotEnoughBandwidth()
  484. {
  485.     CHXSimpleList::Iterator i;
  486.     ASMSourceInfo*          pASMSourceInfo;
  487.     UINT32     ulTotal     = 0;
  488.     BOOL     bIsLive     = FALSE;
  489.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  490.     {
  491. pASMSourceInfo = (ASMSourceInfo*)(*i);
  492. ulTotal += pASMSourceInfo->m_ulSubscribedBw;
  493. if (pASMSourceInfo->m_pSource &&
  494.     pASMSourceInfo->m_pSource->IsLive())
  495. {
  496.     bIsLive = TRUE;
  497. }
  498.     }
  499.     if (bIsLive && ulTotal > m_ulHighestBandwidthAvail)
  500.     {
  501. return TRUE;
  502.     }
  503.     else
  504.     {
  505. return FALSE;
  506.     }
  507. }
  508. STDMETHODIMP
  509. HXSM::UnRegisterSource(HXSource* pSource)
  510. {
  511.     LISTPOSITION lPos;
  512.     ASMSourceInfo*                 pASMSourceInfo = 0;
  513.     ASMStreamInfo*                 pASMStreamInfo;
  514.     BOOL bFound = FALSE;
  515.     lPos = m_pASMSourceInfo->GetHeadPosition();
  516.     DEBUG_OUT(m_pEM, DOL_BWMGR, (s, "UnRegister Source %p %s", pSource, pSource->GetURL()));
  517.     while (lPos)
  518.     {
  519. pASMSourceInfo = (ASMSourceInfo *)m_pASMSourceInfo->GetAt(lPos);
  520. if (pASMSourceInfo->m_pSource == pSource)
  521. {
  522.     m_pASMSourceInfo->RemoveAt(lPos);
  523.     pASMSourceInfo->Done();
  524.     bFound  = TRUE;
  525.     break;
  526. }
  527. m_pASMSourceInfo->GetNext(lPos);
  528.     }
  529.     
  530.     if (!bFound)
  531.     {
  532. return HXR_OK;
  533.     }
  534.     lPos = m_pASMStreamInfo->GetHeadPosition();
  535.     while (lPos)
  536.     {
  537. pASMStreamInfo = (ASMStreamInfo*) m_pASMStreamInfo->GetAt(lPos);
  538. if (pASMStreamInfo->m_pASMSourceInfo == pASMSourceInfo)
  539. {
  540.     /* RemoveAt returns the next position in the list.
  541.      * DO NOT use GetNext if you remove a node.
  542.      */
  543.     lPos = m_pASMStreamInfo->RemoveAt(lPos);
  544.     if (pASMStreamInfo->m_pNegotiator)
  545.     {
  546. pASMStreamInfo->m_pNegotiator->UnRegister();
  547.     }
  548.     delete pASMStreamInfo;
  549. }
  550. else
  551. {
  552.     m_pASMStreamInfo->GetNext(lPos);
  553. }
  554.     }
  555.     
  556.     HX_RELEASE(pASMSourceInfo);
  557.     
  558.     m_ulNumSources--;
  559.     if (m_ulNumSources > 0)
  560.     {
  561. m_State = REDIST;
  562. RecalcAccel();
  563.     }
  564.     return HXR_OK;
  565. }
  566. /* Called by HXPlayer at end of each presentation */
  567. STDMETHODIMP
  568. HXSM::PresentationDone(void)
  569. {
  570.     if (m_ulNumSources == 0)
  571.     {
  572. m_ulHighestBandwidthAvail = 0;
  573. m_ulPeakUsedBandwidth = 0;
  574. m_bInitialHighBwAvail = TRUE;
  575. m_bPipeFull = FALSE;
  576. m_bUpShiftInfoReady = FALSE;
  577. m_ulUpShiftRingPos = 0;
  578. m_ulUpShiftBandwidthAvail = 0;
  579. m_ulNumReportsSinceUpShift = 2;
  580. m_ulOfferToRecalc = 0;
  581. m_State = HX_NONE;
  582. m_bDidOfferUpShiftToRecalc = FALSE;
  583. m_lLoss = 0;
  584. m_ulNextPacketWindow = 0;
  585. m_lPacketCounter = 0;
  586. m_ulUpShiftPastResistanceCount = 0;
  587. m_ulUpShiftTestPointScaleFactor = 4000;
  588.     }
  589.     return HXR_OK;
  590. }
  591. /* If the source has enough data, it may tell the bandwidth
  592.  * manager to cut down on accelerated buffering.
  593.  */
  594. STDMETHODIMP
  595. HXSM::ChangeAccelerationStatus(HXSource* pSource,
  596.         BOOL    bMayBeAccelerated,
  597. BOOL    bUseAccelerationFactor,
  598. UINT32    ulAccelerationFactor)
  599. {
  600.     LISTPOSITION lPos;
  601.     ASMSourceInfo*              pASMSourceInfo = 0;
  602.     BOOL bFound = FALSE;
  603.     lPos = m_pASMSourceInfo->GetHeadPosition();
  604.     while (lPos)
  605.     {
  606. pASMSourceInfo = (ASMSourceInfo *)m_pASMSourceInfo->GetAt(lPos);
  607. if (pASMSourceInfo->m_pSource == pSource)
  608. {
  609.     bFound  = TRUE;
  610.     break;
  611. }
  612. m_pASMSourceInfo->GetNext(lPos);
  613.     }
  614.     /* This assert may happen if you are in PNA and are in the debugger
  615.      * accumulating tons of data at the networking layer
  616.      */
  617. //    HX_ASSERT(bFound);
  618.     if (bFound)
  619.     {
  620. pASMSourceInfo->ChangeAccelerationStatus(bMayBeAccelerated,
  621.     bUseAccelerationFactor, ulAccelerationFactor);
  622.     }
  623.     else
  624.     {
  625. /* Hmmm... ASM cannot help us here */
  626. /* Must be PNA. This may happen in case of TCP where the server sends 
  627.  * data 300% faster than the content bandwidth.
  628.  * Do the old style flow control by Pausing/Resuming the server
  629.  */
  630. if (!bMayBeAccelerated)
  631. {
  632.     pSource->DoPause();
  633. }
  634. else
  635. {
  636.     pSource->DoResume();
  637. }
  638.     }
  639.     return HXR_OK;
  640. }
  641. //ChangeBW() allows setting the maximum bandwidth limit on a source. Called by 
  642. //RTSPProtocol::HandleSetParameterRequest()
  643. STDMETHODIMP
  644. HXSM::ChangeBW(UINT32 newBW, HXSource* pSource)
  645. {
  646.     CHXSimpleList::Iterator     ii;
  647.     ASMSourceInfo*                 pASMSourceInfo;  
  648.     BOOL bSourceFound = FALSE;     
  649.     DEBUG_OUT(m_pEM, DOL_BWMGR, (s,"(%p)Request to change BW to %ld", pSource, newBW));
  650.     for(ii = m_pASMSourceInfo->Begin(); ii != m_pASMSourceInfo->End(); ++ii)
  651.     {
  652. pASMSourceInfo = (ASMSourceInfo*)(*ii);
  653. if (pASMSourceInfo->m_pSource == pSource) //Comparing Pointers
  654. {
  655.     bSourceFound = TRUE;
  656.     ASMRuleBook* pRuleBook = pASMSourceInfo->m_pMasterRuleBook;
  657.     BOOL bDownShift = FALSE;
  658.     if (pRuleBook)
  659.     {
  660. UINT32 ulNumStreamsForThisSource = 
  661.     pASMSourceInfo->m_pSource->GetStreamCount();
  662. BOOL* pCurrentSubInfo = new BOOL[pRuleBook->GetNumRules()];
  663. HXSMUpdateSubscriptionVars(m_pSubscriptionVariables, 
  664.    newBW, FALSE, 0);
  665. HX_RESULT lResult =
  666.     pRuleBook->GetSubscription(pCurrentSubInfo, m_pSubscriptionVariables);
  667. HX_ASSERT(lResult == HXR_OK);
  668. for (UINT16 idxRule = 0; idxRule < pRuleBook->GetNumRules(); 
  669. idxRule++)
  670. {
  671.     if (pCurrentSubInfo[idxRule])
  672.     {
  673. IHXValues* pProps = 0;
  674. // Set Distribution
  675. pRuleBook->GetProperties(idxRule, pProps);
  676. for (UINT32 j = 0; j < ulNumStreamsForThisSource; j++)
  677. {     
  678.     UINT8 pTemp[128];
  679.     IHXBuffer* pBw = NULL;
  680.     // Don't assume that streamid == index in pASMSourceInfo->m_pStreams[j]
  681.     SafeSprintf((char *)pTemp, 128, "Stream%ldBandwidth", pASMSourceInfo->m_pStreams[j]->m_ulStreamNumber); /* Flawfinder: ignore */
  682.     /*
  683.     * if this tripps either there's a bug in here or
  684.     * the content is messed up
  685.     *
  686.     */ 
  687.     HX_VERIFY(HXR_OK==
  688. pProps->GetPropertyCString((char*)pTemp, pBw));
  689.     if (pBw)
  690.     {
  691. BOOL bFoundMax=FALSE;
  692. UINT32 newMaxBW = (UINT32) 
  693.     (atoi((char*)pBw->GetBuffer()));
  694. for(int cnt =0; 
  695. cnt < (int)pASMSourceInfo->m_pStreams[j]->
  696.     m_ulNumThresholds; cnt++)
  697. {
  698.     if (newMaxBW == 
  699. pASMSourceInfo->m_pStreams[j]->m_pThreshold[cnt])
  700.     {
  701. bFoundMax = TRUE;
  702. pASMSourceInfo->m_pStreams[j]->
  703.     m_ulMaxEffectiveThreshold = cnt;
  704. // We are downshifting!!
  705. if ((int)pASMSourceInfo->m_pStreams[j]->
  706.     m_ulThresholdPosition > cnt) 
  707. {
  708.     bDownShift = TRUE;
  709.     pASMSourceInfo->m_pStreams[j]->
  710. m_ulThresholdPosition = cnt;
  711. }
  712. // We will try to upshift
  713. else if ((int)pASMSourceInfo->m_pStreams[j]->
  714.     m_ulThresholdPosition < cnt)  
  715.     pASMSourceInfo->m_bTryToUpShift = TRUE;
  716. break;
  717.     }
  718. }
  719. HX_ASSERT(bFoundMax);
  720. if (bDownShift || pASMSourceInfo->m_bTryToUpShift)
  721.     pASMSourceInfo->m_bAdjustBandwidth = TRUE;
  722. pBw->Release();
  723. pBw = NULL;
  724.     } 
  725. HX_RELEASE(pProps);
  726.     } 
  727.     }
  728.     //Assume a single stream source, or a fixedbw source .. 
  729.     //for live, we have more than 1 streams ??
  730.     else      
  731.     {
  732. BOOL bFoundMax = FALSE;
  733. UINT32 numStreams = pASMSourceInfo->m_pSource->GetStreamCount();
  734. //for(int j = 0; j < numStreams; j++)
  735. // {
  736. for(int cnt =0; 
  737. cnt < (int)pASMSourceInfo->m_pStreams[0]->m_ulNumThresholds; cnt++)
  738. {
  739.     if (newBW == pASMSourceInfo->m_pStreams[0]->m_pThreshold[cnt])
  740.     {
  741. bFoundMax = TRUE;
  742. // We are downshifting!!
  743. if ((int)pASMSourceInfo->m_pStreams[0]->m_ulThresholdPosition > cnt) 
  744. {
  745.     bDownShift = TRUE;
  746.     pASMSourceInfo->m_pStreams[0]->m_ulThresholdPosition = cnt;
  747. }
  748. // We are upshifting
  749. else if ((int)pASMSourceInfo->m_pStreams[0]->m_ulThresholdPosition < cnt) 
  750.     pASMSourceInfo->m_bTryToUpShift = TRUE;
  751. pASMSourceInfo->m_pStreams[0]->m_ulMaxEffectiveThreshold = cnt;
  752. break;
  753.     }
  754. }
  755. if (bDownShift || pASMSourceInfo->m_bTryToUpShift)
  756.     pASMSourceInfo->m_bAdjustBandwidth = TRUE;
  757.     }
  758.     m_State = REDIST;
  759.     RecalcAccel();
  760.     } 
  761.     HX_ASSERT(bSourceFound);
  762.     return HXR_OK; 
  763. }
  764. void
  765. HXSM::Recalc()
  766. {
  767.     CHXSimpleList::Iterator     i, j;
  768.     ASMSourceInfo*                 pASMSourceInfo;
  769.     ASMStreamInfo*                 pASMStreamInfo;
  770.     INT32 lAggregateBandwidthUsage = 0;
  771.     INT32 lAggregateBandwidthSent = 0;
  772.     UINT32 ulSourceCount;
  773.     UINT32 ulStreamCount;
  774.     float fBiasMean = (float) 0.;
  775.     ulSourceCount = m_pASMSourceInfo->GetCount();
  776.     ulStreamCount = m_pASMStreamInfo->GetCount();
  777.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  778.     {
  779. pASMSourceInfo = (ASMSourceInfo*)(*i);
  780.         /* Init these for later */
  781. pASMSourceInfo->m_ulMasterOffer = 0;
  782. pASMSourceInfo->m_bTimeStampDelivery = FALSE;
  783.     }
  784.     lAggregateBandwidthUsage = m_ulOfferToRecalc;
  785.     INT32 lCorrectAggregateBandwidthUsage = lAggregateBandwidthUsage;
  786.     /*
  787.      * For each stream that is at a fixed bitrate, remove that bitrate
  788.      * from our available bandwidth.
  789.      */
  790.     for (j = m_pASMStreamInfo->Begin(); j != m_pASMStreamInfo->End(); ++j)
  791.     {
  792.         INT32 lBias;
  793. pASMStreamInfo = (ASMStreamInfo*)(*j);
  794. HX_VERIFY(HXR_OK == pASMStreamInfo->m_pBias->GetBiasFactor(lBias));
  795. fBiasMean += lBias;
  796. if (pASMStreamInfo->m_ulFixedBandwidth)
  797. {
  798.     lAggregateBandwidthUsage -= pASMStreamInfo->m_ulFixedBandwidth;
  799.     ulStreamCount--;
  800. }
  801. /* Init this for later */
  802. pASMStreamInfo->m_ulMasterRuleBookSetOffer = 0;
  803.     }
  804.     /* fBiasMean is not needed if everything has a fixed bandwidth */
  805.     if (ulStreamCount != 0)
  806.     {
  807. fBiasMean /= (float)ulStreamCount;
  808.     }
  809.     /*
  810.      * Calculate the offer for each source that has a master rulebook
  811.      * defining it's bandwidth division.
  812.      */
  813.     INT32 lNewAggregateBandwidthUsage = lAggregateBandwidthUsage;
  814.     for (j = m_pASMStreamInfo->Begin(); j != m_pASMStreamInfo->End(); ++j)
  815.     {
  816. INT32 lBias;
  817. pASMStreamInfo = (ASMStreamInfo*)(*j);
  818. HX_VERIFY(HXR_OK == pASMStreamInfo->m_pBias->GetBiasFactor(lBias));
  819. if (pASMStreamInfo->m_pASMSourceInfo->m_pMasterRuleBook)
  820. {
  821.     UINT32 ulOffer = 
  822. (UINT32)(lAggregateBandwidthUsage / (float)ulStreamCount);
  823.     ulOffer += 
  824. (UINT32)(((float)lBias - fBiasMean) *
  825. ((float)lAggregateBandwidthUsage / 100.0) *
  826. (2.0 / (float)ulStreamCount));
  827.     pASMStreamInfo->m_pASMSourceInfo->m_ulMasterOffer += ulOffer;
  828.     lNewAggregateBandwidthUsage -= ulOffer;
  829. }
  830.     }
  831.     lAggregateBandwidthUsage = lNewAggregateBandwidthUsage;
  832.     /*
  833.      * For each source that has a master rule book, evaluate it to find
  834.      * out how much to distribute to each stream.
  835.      */
  836.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  837.     {
  838. pASMSourceInfo = (ASMSourceInfo*)(*i);
  839. ASMRuleBook* pRuleBook = pASMSourceInfo->m_pMasterRuleBook;
  840. if (pRuleBook)
  841. {
  842.     UINT32 ulNumStreamsForThisSource = 
  843. pASMSourceInfo->m_pSource->GetStreamCount();
  844.     BOOL* pCurrentSubInfo = new BOOL[pRuleBook->GetNumRules()];
  845.     HXSMUpdateSubscriptionVars(m_pSubscriptionVariables, 
  846.        pASMSourceInfo->m_ulMasterOffer,
  847.        FALSE, 0);
  848.     HX_RESULT lResult =
  849. pRuleBook->GetSubscription(pCurrentSubInfo, m_pSubscriptionVariables);
  850.     HX_ASSERT(lResult == HXR_OK);
  851.     for (UINT16 idxRule = 0; idxRule < pRuleBook->GetNumRules();
  852. idxRule++)
  853.     {
  854. if (pCurrentSubInfo[idxRule])
  855. {
  856.     IHXValues* pProps = 0;
  857.     // Set Distribution
  858.     pRuleBook->GetProperties(idxRule, pProps);
  859.     for (UINT32 j = 0; j < ulNumStreamsForThisSource; j++)
  860.     {
  861. UINT8       pTemp[128];
  862. IHXBuffer* pBw = NULL;
  863. HX_RESULT   hxResult;
  864. // Don't assume that streamid == index in pASMSourceInfo->m_pStreams[j]
  865.                         SafeSprintf((char *)pTemp, 128, "Stream%ldBandwidth", pASMSourceInfo->m_pStreams[j]->m_ulStreamNumber); /* Flawfinder: ignore */
  866. /*
  867.  * if this tripps either there's a bug in here or
  868.  * the content is messed up
  869.  *
  870.  */
  871. //If the Stream?Bandwidth property isn't found for
  872. //all streams don't worry about it. Not all streams
  873. //may have rule books.
  874. hxResult = pProps->GetPropertyCString((char *)pTemp, pBw);
  875. if(HXR_OK==hxResult && pBw)
  876. {
  877.     pASMSourceInfo->m_pStreams[j]->
  878. m_ulMasterRuleBookSetOffer =
  879. atoi((char*)pBw->GetBuffer());
  880.     pBw->Release();
  881.     pBw = NULL;
  882. }
  883. else
  884. {
  885.     pASMSourceInfo
  886. ->m_pStreams[j]
  887. ->m_ulMasterRuleBookSetOffer = 0;
  888. }//HXR_OK==hxResult && pBw
  889.     }
  890.     HX_RELEASE(pProps);
  891.     break;
  892. }
  893.     }
  894.     delete [] pCurrentSubInfo;
  895. }
  896.     }
  897.     /*
  898.      *  Now go through each of the streams that are not at a
  899.      *  fixed bitrate and try to distribute the rest of the bandwidth.
  900.      */
  901.     UINT32 ulTakenBandwidth = 0;
  902.     for (j = m_pASMStreamInfo->Begin(); j != m_pASMStreamInfo->End(); ++j)
  903.     {
  904. INT32 lBias;
  905. pASMStreamInfo = (ASMStreamInfo*)(*j);
  906. if (pASMStreamInfo->m_ulFixedBandwidth != 0)
  907. {
  908.     ulTakenBandwidth += pASMStreamInfo->m_ulFixedBandwidth;
  909.     pASMStreamInfo->m_ulResistanceToLower = 0xffffffff;
  910.     continue;
  911. }
  912. HX_VERIFY(HXR_OK == pASMStreamInfo->m_pBias->GetBiasFactor(lBias));
  913. HX_ASSERT(pASMStreamInfo->m_pThreshold != NULL);
  914. UINT32 ulOffer = 0;
  915. if (pASMStreamInfo->m_pASMSourceInfo->m_bPerfectPlay)
  916. {
  917.     UINT32 i = pASMStreamInfo->m_ulMaxEffectiveThreshold;
  918.     ulTakenBandwidth += (UINT32)pASMStreamInfo->m_pThreshold[i];
  919.     pASMStreamInfo->m_ulResistanceToLower = 0xffffffff;
  920.     pASMStreamInfo->m_ulOffer = (UINT32)pASMStreamInfo->m_pThreshold[i];
  921.     pASMStreamInfo->m_ulThresholdPosition = i;
  922.     /*
  923.      * If we are in perfect play mode, just select the highest bandwidth rule
  924.      * and don't negotiate any further.
  925.      */
  926.     continue;
  927. }
  928. if (pASMStreamInfo->m_ulMasterRuleBookSetOffer)
  929. {
  930.     ulOffer = pASMStreamInfo->m_ulMasterRuleBookSetOffer - 1;
  931. }
  932. else
  933. {
  934.     ulOffer =
  935. (UINT32)(lAggregateBandwidthUsage / (float)ulStreamCount);
  936.     ulOffer += 
  937. (UINT32)(((float)lBias - fBiasMean) *
  938. ((float)lAggregateBandwidthUsage / 100.0) *
  939. (2.0 / (float)ulStreamCount));
  940. }
  941. HX_ASSERT(pASMStreamInfo->m_ulMaxEffectiveThreshold >= 0);
  942. if (pASMStreamInfo->m_ulMaxEffectiveThreshold == 0)
  943. {
  944.     HX_ASSERT(pASMStreamInfo->m_pThreshold[0] == 0);
  945.     ulTakenBandwidth += (UINT32)pASMStreamInfo->m_pThreshold[0];
  946.     pASMStreamInfo->m_ulResistanceToLower = 0xffffffff;
  947. }
  948. else
  949. {
  950.     for (UINT32 i = 1; i <= pASMStreamInfo->m_ulMaxEffectiveThreshold; i++)
  951.     {
  952. if ((ulOffer <= pASMStreamInfo->m_pThreshold[i]) ||
  953. (i == (pASMStreamInfo->m_ulMaxEffectiveThreshold)))
  954. {
  955.     ulTakenBandwidth += (UINT32)pASMStreamInfo->m_pThreshold[i];
  956.     if (i == 1)
  957.     {
  958. pASMStreamInfo->m_ulResistanceToLower = 0xffffffff;
  959.     }
  960.     else
  961.     {
  962. pASMStreamInfo->m_ulResistanceToLower = (ulOffer -
  963.     (UINT32)pASMStreamInfo->m_pThreshold[i - 1]) * ulOffer;
  964.     }
  965.     pASMStreamInfo->
  966. m_ulOffer = ulOffer;
  967.     pASMStreamInfo->m_ulThresholdPosition = i;
  968.     break;
  969. }
  970.     }
  971. }
  972.     }
  973.     lAggregateBandwidthUsage = lCorrectAggregateBandwidthUsage;
  974. tryagain:
  975.     if (lAggregateBandwidthUsage < (INT32)ulTakenBandwidth)
  976.     {
  977. /* Resistance is Futile.  You will be Real(tm)lyAssimilated */
  978. UINT32 ulLowestResistance = 0xffffffff;
  979. ASMStreamInfo* pLowestResistanceStream  = 0;
  980. for (j = m_pASMStreamInfo->Begin(); j != m_pASMStreamInfo->End(); ++j)
  981. {
  982.     pASMStreamInfo = (ASMStreamInfo*)(*j);
  983.     if (pASMStreamInfo->m_ulResistanceToLower < ulLowestResistance)
  984.     {
  985. ulLowestResistance = pASMStreamInfo->m_ulResistanceToLower;
  986. pLowestResistanceStream = pASMStreamInfo;
  987.     }
  988. }
  989. if (ulLowestResistance == 0xffffffff)
  990. {
  991. }
  992. else
  993. {
  994.     ulTakenBandwidth -= (UINT32)
  995. pLowestResistanceStream->m_pThreshold[pLowestResistanceStream->m_ulThresholdPosition];
  996.     pLowestResistanceStream->m_ulThresholdPosition--;
  997.     ulTakenBandwidth += (UINT32)
  998. pLowestResistanceStream->m_pThreshold[pLowestResistanceStream->m_ulThresholdPosition];
  999.     if (pLowestResistanceStream->m_ulThresholdPosition == 1)
  1000.     {
  1001. pLowestResistanceStream->m_ulResistanceToLower = 0xffffffff;
  1002.     }
  1003.     else
  1004.     {
  1005. pLowestResistanceStream->m_ulResistanceToLower = (pLowestResistanceStream->m_ulOffer -
  1006.     (UINT32)pLowestResistanceStream->m_pThreshold[
  1007.     pLowestResistanceStream->m_ulThresholdPosition - 1]) *
  1008.     pLowestResistanceStream->m_ulOffer;
  1009.     }
  1010.     goto tryagain;
  1011. }
  1012.     }
  1013.     UINT32 ulLeftOverForDropByN = lAggregateBandwidthUsage - ulTakenBandwidth;
  1014.     BOOL bForce = FALSE;
  1015.     for (j = m_pASMStreamInfo->Begin(); j != m_pASMStreamInfo->End(); ++j)
  1016.     {
  1017. pASMStreamInfo = (ASMStreamInfo*)(*j);
  1018. UINT32 ulBw = 1;
  1019. if (pASMStreamInfo->m_ulFixedBandwidth)
  1020. {
  1021.     ulBw = pASMStreamInfo->m_ulFixedBandwidth;
  1022. }
  1023. else
  1024. {
  1025.     ulBw = (UINT32)
  1026.     pASMStreamInfo->m_pThreshold[pASMStreamInfo->m_ulThresholdPosition];
  1027. }
  1028. UINT32 ulBwOffered = ulBw;
  1029. if (ulBw == 1)
  1030. {
  1031.     // Hack Alert for DropByN. XXXSMP
  1032.     ulBwOffered = ulBw = ulLeftOverForDropByN;
  1033. }
  1034. if ((ulBw != pASMStreamInfo->m_ulLastBandwidth) &&
  1035.     (!pASMStreamInfo->m_ulFixedBandwidth))
  1036. {
  1037.     bForce = TRUE;
  1038. }
  1039. pASMStreamInfo->m_pRuleGather->
  1040.     RuleGather(&pASMStreamInfo->m_pASMSourceInfo->
  1041.     m_SubscriptionChanges);
  1042. pASMStreamInfo->SetLastBandwidth(ulBw);
  1043. HX_ASSERT(ulBw == ulBwOffered);
  1044. //update the HXASMStream with our new bandwidth
  1045. pASMStreamInfo->NotifyNewBandwidth();
  1046. //update the source's knowledge of tsd
  1047. pASMStreamInfo->NotifyTimeStampDelivery();
  1048. //if the stream is behind, tell the server to chill
  1049. pASMStreamInfo->NotifyLimitBandwidth(ulBwOffered);
  1050. pASMStreamInfo->m_pRuleGather->RuleGather(0);
  1051.     }
  1052.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  1053.     {
  1054. pASMSourceInfo = (ASMSourceInfo*)(*i);
  1055. if (!pASMSourceInfo->m_SubscriptionChanges.IsEmpty())
  1056. {
  1057.     pASMSourceInfo->m_pStreams[0]->m_pRuleGather->
  1058. RuleFlush(&pASMSourceInfo->m_SubscriptionChanges);
  1059.     for (j = pASMSourceInfo->m_SubscriptionChanges.Begin();
  1060.  j != pASMSourceInfo->m_SubscriptionChanges.End(); ++j)
  1061.     {
  1062. RTSPSubscription* pSub = (RTSPSubscription*)(*j);
  1063. delete pSub;
  1064.     }
  1065.     pASMSourceInfo->m_SubscriptionChanges.RemoveAll();
  1066. }
  1067.     }
  1068.     if (m_State == REDO_ACCEL)
  1069.     {
  1070. RecalcAccel();
  1071. return;
  1072.     }
  1073.     if (m_State == CONGESTION)
  1074.     {
  1075. RecalcAccel();
  1076. return;
  1077.     }
  1078.     if (m_State == INIT)
  1079.     {
  1080. m_State = INIT_REDIST;
  1081. RecalcAccel();
  1082. return;
  1083.     }
  1084.     if (bForce)
  1085.     {
  1086. m_State = REDO_ACCEL;
  1087. RecalcAccel();
  1088. return;
  1089.     }
  1090. }
  1091. void
  1092. HXSM::RecalcAccel()
  1093. {
  1094.     CHXSimpleList::Iterator     i, j;
  1095.     ASMSourceInfo*                 pASMSourceInfo;
  1096.     ASMStreamInfo*                 pASMStreamInfo;
  1097.     UINT32 ulAggregateUsed = 0;
  1098.     UINT32 ulTotalMaxSubscribedBw = 0;
  1099.     if (m_State == INIT)
  1100.     {
  1101. m_ulOfferToRecalc = m_ulHighestBandwidthAvail;
  1102. if (m_ulOfferToRecalc > m_ulMaxAccelBitRate)
  1103. {
  1104.     m_ulOfferToRecalc = m_ulMaxAccelBitRate;
  1105. }
  1106. #ifdef MOREDEBUG
  1107. DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
  1108. "INIT Offer to Recalc() %d", m_ulOfferToRecalc));
  1109. #endif
  1110. Recalc();
  1111. return;
  1112.     }
  1113.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  1114.     {
  1115. pASMSourceInfo = (ASMSourceInfo*)(*i);
  1116. pASMSourceInfo->m_ulSubscribedBw = 0;
  1117. pASMSourceInfo->m_ulMaxSubscribedBw = 0;
  1118.     }
  1119.     for (j = m_pASMStreamInfo->Begin(); j != m_pASMStreamInfo->End(); ++j)
  1120.     {
  1121. pASMStreamInfo = (ASMStreamInfo*)(*j);
  1122. if (pASMStreamInfo->m_ulFixedBandwidth)
  1123. {
  1124.     pASMStreamInfo->m_pASMSourceInfo->m_ulSubscribedBw += 
  1125. pASMStreamInfo->m_ulFixedBandwidth;
  1126.     pASMStreamInfo->m_pASMSourceInfo->m_ulMaxSubscribedBw += 
  1127. pASMStreamInfo->m_ulFixedBandwidth;
  1128.     ulTotalMaxSubscribedBw += pASMStreamInfo->m_ulFixedBandwidth;
  1129.     ulAggregateUsed += pASMStreamInfo->m_ulFixedBandwidth;
  1130. }
  1131. else
  1132. {
  1133.     pASMStreamInfo->m_pASMSourceInfo->m_ulSubscribedBw += (UINT32)
  1134. pASMStreamInfo->m_pThreshold[
  1135.     pASMStreamInfo->m_ulThresholdPosition];
  1136.     HX_ASSERT(pASMStreamInfo->m_pASMSourceInfo->m_ulSubscribedBw < 0x7fffffff);
  1137.     pASMStreamInfo->m_pASMSourceInfo->m_ulMaxSubscribedBw += (UINT32)
  1138. pASMStreamInfo->m_pThreshold[
  1139.     pASMStreamInfo->m_ulMaxEffectiveThreshold];
  1140.     ulTotalMaxSubscribedBw += (UINT32)pASMStreamInfo->m_pThreshold[
  1141.     pASMStreamInfo->m_ulMaxEffectiveThreshold];
  1142.     ulAggregateUsed += (UINT32)
  1143. pASMStreamInfo->m_pThreshold[
  1144.     pASMStreamInfo->m_ulThresholdPosition];
  1145. }
  1146.     }
  1147.     UINT32 ulNumBehindSources = 0;
  1148.     UINT32 ulNumSlightlyBehindSources = 0;
  1149.     INT32  lAggregateBandwidthUsage = 0;
  1150.     INT32  ulMaxNeededBW                = 0;
  1151.     BOOL   bAllZeroBw = TRUE;
  1152.     BOOL   bFastStart                   = FALSE;
  1153.     
  1154.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  1155.     {
  1156. pASMSourceInfo = (ASMSourceInfo*)(*i);
  1157. if (pASMSourceInfo->m_ulLastSetDelivery == 0xffffffff)
  1158. {
  1159.     pASMSourceInfo->m_ulLastSetDelivery = pASMSourceInfo->m_ulSubscribedBw;
  1160. }
  1161.         // if ANY of the sources are fast start then we are in 
  1162.         // fast start mode. We may wish to re-visit this decision!
  1163.         // this comment is for you Rahul!
  1164.         if (pASMSourceInfo && pASMSourceInfo->m_pSource)
  1165.         {
  1166.             bFastStart = bFastStart | pASMSourceInfo->m_pSource->m_bFastStart;
  1167.         }
  1168. ulNumBehindSources += pASMSourceInfo->m_bBehind ? 1 : 0;
  1169. ulNumSlightlyBehindSources += pASMSourceInfo->m_bSlightlyBehind ? 1 : 0;
  1170. lAggregateBandwidthUsage += pASMSourceInfo->GetBandwidth();
  1171. if (!pASMSourceInfo->GetBandwidth())
  1172.     lAggregateBandwidthUsage += pASMSourceInfo->m_ulSubscribedBw;
  1173. else
  1174.     bAllZeroBw = FALSE;
  1175.         ulMaxNeededBW += pASMSourceInfo->m_ulMaxSubscribedBw;
  1176.     }
  1177.     // so if we are in fast start, let's check to see if we don't want to be in
  1178.     // fast start!
  1179.     double maxPossibleAccelRatio = 0.;
  1180.     if (ulMaxNeededBW > 0.)
  1181.     {
  1182.         maxPossibleAccelRatio = (double) m_ulOriginalHighestBandwidthAvail / (double) ulMaxNeededBW;
  1183.     }
  1184.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  1185.     {
  1186. pASMSourceInfo = (ASMSourceInfo*)(*i);
  1187.         // I could check here for pASMSourceInfo->m_pSource->m_bFastStart, but really
  1188.         // does it matter?
  1189.         if (pASMSourceInfo && pASMSourceInfo->m_pSource)
  1190.         {
  1191.             pASMSourceInfo->m_pSource->SetMaxPossibleAccelRatio(maxPossibleAccelRatio);
  1192.         }
  1193.         // turn this stuff of if we are on modem. *sigh* It probably sort of works on 
  1194.         // modems too. This value makes it work on ISDN, that's ok by me, but if people
  1195.         // don't like it, I can change it.         
  1196.         if (maxPossibleAccelRatio < 1.5 || 
  1197.             (m_ulOriginalHighestBandwidthAvail < 110000)) // it now works on DSL or higher
  1198.         {
  1199.     bFastStart = FALSE;
  1200.             if (pASMSourceInfo->m_pSource->m_bFastStart)
  1201.     {
  1202.                 DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,"(%p)ASM %d - Leaving TurboPlay", pASMSourceInfo->m_pSource, __LINE__));
  1203. pASMSourceInfo->m_pSource->LeaveFastStart(TP_OFF_BY_NOTENOUGHBW);
  1204.     }
  1205.         }
  1206.         // Are we currently asking for less than max? Is so Disable!
  1207. //
  1208. // XXX HP I am not sure the following logic is valid, it's possible 
  1209. //   pASMSourceInfo->m_ulSubscribedBw < pASMSourceInfo->m_ulMaxSubscribedBw because the
  1210. //   master rulebook defines so even though we have plenty of bandwidth(i.e. maxPossibleAccelRatio > 1.5)
  1211. //   If it's really the case that the source doesn't subscribe to its max. bandwidth because
  1212. //   we don't have enough bandwidth, then maxPossibleAccelRatio < 1.5 and we should left faststart
  1213. //   already
  1214. /*
  1215.         if (pASMSourceInfo && pASMSourceInfo->GetBandwidth() && pASMSourceInfo->m_ulMaxSubscribedBw != pASMSourceInfo->m_ulSubscribedBw
  1216.             &&  pASMSourceInfo->m_pSource->m_bFastStart)
  1217.         {
  1218.             DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,"ASM %d - Leaving TurboPlay", __LINE__));
  1219.             DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,"%d %d %d", pASMSourceInfo->m_ulMaxSubscribedBw, pASMSourceInfo->GetBandwidth(),pASMSourceInfo->m_ulSubscribedBw));
  1220.             pASMSourceInfo->m_pSource->LeaveFastStart();
  1221.         }
  1222. */
  1223.     }
  1224.     if (m_bPipeFull == TRUE)
  1225.     {
  1226. /*
  1227.  * Adjust the highest available bandwidth because we have found
  1228.  * the maximum bandwidth that the pipe can handle.  We do this
  1229.  * so that sources that get added in the future will have
  1230.  * some information about the max. bandwidth that exists.  This
  1231.  * value is aggresive because a source will want to consume everything
  1232.  * it can and fall back if it goes over the top.
  1233.  */
  1234. HX_ASSERT(lAggregateBandwidthUsage >= 100);
  1235. if (lAggregateBandwidthUsage < 100)
  1236. {
  1237.     /*
  1238.      * Please have at *least* 100bps before attempting to
  1239.      * run the RealPlayer.
  1240.      */
  1241.     lAggregateBandwidthUsage = 100;
  1242. }
  1243. m_ulHighestBandwidthAvail = (UINT32)(lAggregateBandwidthUsage);
  1244. m_ulPeakUsedBandwidth = (UINT32)(lAggregateBandwidthUsage);
  1245. m_bInitialHighBwAvail = FALSE;
  1246. m_bPipeFull = FALSE;
  1247.     }
  1248.     if (m_State == REDIST)
  1249.     {
  1250.         m_State = REDO_ACCEL;
  1251.         m_ulOfferToRecalc = m_ulHighestBandwidthAvail;
  1252.         Recalc();
  1253. return;
  1254.     }
  1255.     if ((m_State == REDO_ACCEL) || (m_State == INIT_REDIST))
  1256.     {
  1257. UINT32 ulBigValue;
  1258. if ((m_bInitialHighBwAvail) || (m_State == REDO_ACCEL))
  1259. {
  1260.     ulBigValue = m_ulPeakUsedBandwidth;
  1261.     if (bFastStart && (m_State == INIT_REDIST))
  1262.     {
  1263. ulBigValue = m_ulMaxAccelBitRate;
  1264.     } 
  1265.     else if ((INT32)ulBigValue > lAggregateBandwidthUsage)
  1266.     {
  1267. ulBigValue = lAggregateBandwidthUsage;
  1268.     }
  1269. }
  1270. else
  1271. {
  1272.     /*
  1273.      * If your state is REDO_ACCEL & we have an imperical value
  1274.      * then maybe we should use this (ABU) instead of the above,
  1275.      * but this value may not be completely up to date?
  1276.      */
  1277.     ulBigValue = lAggregateBandwidthUsage;
  1278. }
  1279. HX_ASSERT(ulBigValue > 0); // Rahul's Crazy, This won't ever happen!
  1280. for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  1281. {
  1282.     pASMSourceInfo = (ASMSourceInfo*)(*i);
  1283.     IHXThinnableSource* pThin = 0;
  1284.     UINT32 ulSourceBandwidth = pASMSourceInfo->m_ulSubscribedBw;
  1285.     UINT32 ulNewValue = 
  1286.     (UINT32)(
  1287.     ((float)ulSourceBandwidth /
  1288.     (float)ulAggregateUsed) *
  1289.     (float)(ulBigValue));
  1290.     if ((HXR_OK == pASMSourceInfo->m_pSource->
  1291. QueryInterface(IID_IHXThinnableSource, (void **)&pThin)))
  1292.     {
  1293. if ((ulNewValue > (pASMSourceInfo->m_ulLastSetDelivery * 1.02)) ||
  1294.     (ulNewValue < (pASMSourceInfo->m_ulLastSetDelivery * 0.98)) ||
  1295.     (pASMSourceInfo->m_bAdjustBandwidth && pASMSourceInfo->m_pSource->IsLive()))
  1296. {
  1297.                     BOOL bFastStart = FALSE;
  1298.                     
  1299.                     if (pASMSourceInfo && pASMSourceInfo->m_pSource)
  1300.                     {
  1301.                         bFastStart = pASMSourceInfo->m_pSource->m_bFastStart;
  1302.                     }
  1303.                     if (bFastStart)
  1304.                     {
  1305.         if (ulNewValue > (pASMSourceInfo->m_ulMaxSubscribedBw * m_fAccelerationFactor))
  1306.         {
  1307.     ulNewValue = (UINT32) 
  1308.         (pASMSourceInfo->m_ulMaxSubscribedBw * m_fAccelerationFactor);
  1309.         }
  1310.                 
  1311.                         // if the server says to cap the value, we cap the value!
  1312.                         if (pASMSourceInfo && pASMSourceInfo->m_pSource && ulNewValue  > pASMSourceInfo->m_pSource->m_ulMaxBandwidth * 1000 )
  1313.                         {
  1314.                             ulNewValue = pASMSourceInfo->m_pSource->m_ulMaxBandwidth * 1000;
  1315.                         }
  1316.                         // if the value is greater is than the pipe set it to a 
  1317.                         // little less than the pipe!
  1318.                         if (ulNewValue  > m_ulOriginalHighestBandwidthAvail)
  1319.                         {
  1320.                             ulNewValue = m_ulOriginalHighestBandwidthAvail;
  1321.                         }
  1322.                     }
  1323.                     else
  1324.                     {
  1325.         if (ulNewValue > (pASMSourceInfo->m_ulMaxSubscribedBw * 4))
  1326.         {
  1327.     ulNewValue = (UINT32) 
  1328.         (pASMSourceInfo->m_ulMaxSubscribedBw * 4);
  1329.         }
  1330. /*
  1331.  * Live streams get capped at 107% of Max to prevent 
  1332.  * unneeded bandwidht modulation.
  1333.  */
  1334. if ((pASMSourceInfo->m_pSource->IsLive()) &&
  1335.    (ulNewValue >
  1336. (pASMSourceInfo->m_ulMaxSubscribedBw * 1.07)))
  1337. {
  1338.     ulNewValue = (UINT32)
  1339. (pASMSourceInfo->m_ulMaxSubscribedBw * 1.07);
  1340. }
  1341.     }
  1342.     pASMSourceInfo->m_bAdjustBandwidth = FALSE;
  1343.     if ((ulNewValue > (pASMSourceInfo->m_ulMaxSubscribedBw)) &&
  1344. (ulNewValue > (ulSourceBandwidth * 3)) &&
  1345. (pASMSourceInfo->m_ulLastSetDelivery >
  1346.     pASMSourceInfo->m_ulMaxSubscribedBw))
  1347.     {
  1348. /*
  1349.  * If we are already accelerating 3x subscribed bandwidth
  1350.  * and we are about to upshift beyond the max possible
  1351.  * bandwidth, then let's stop and take a breather just
  1352.  * above the max subscription.  This prevents us from
  1353.  * buffering huge amounts of the crappy low bw stream.
  1354.  */
  1355. UINT32 ulTemp;
  1356. ulTemp = (UINT32) 
  1357.     (pASMSourceInfo->m_ulMaxSubscribedBw * 1.10);
  1358. ulNewValue = MIN(ulTemp, ulNewValue);
  1359.     }
  1360.     if ((ulNewValue < ulSourceBandwidth) && (ulSourceBandwidth > 10))
  1361.     {
  1362. pASMSourceInfo->m_pSource->EnterBufferedPlay();
  1363.     } 
  1364.          if (ulNewValue >= ulSourceBandwidth)
  1365.     {
  1366. pASMSourceInfo->m_pSource->LeaveBufferedPlay();
  1367.     }
  1368.     if ((ulNewValue >= pASMSourceInfo->m_ulLastSetDelivery) &&
  1369. (!pASMSourceInfo->m_bMayBeAccelerated) && 
  1370. (!pASMSourceInfo->m_bTryToUpShift))
  1371.     {
  1372. goto dont_actually_set_the_rate;
  1373.     }
  1374.     if (ulNewValue > m_ulResistanceBitRate && !bFastStart)
  1375.     {
  1376. UINT32 ulActualResistanceBitRate = m_ulResistanceBitRate;
  1377. if (ulActualResistanceBitRate < ulAggregateUsed)
  1378. {
  1379.     ulActualResistanceBitRate = (UINT32)
  1380.         (ulAggregateUsed * 1.05);
  1381. }
  1382. if (ulNewValue > ulActualResistanceBitRate)
  1383. {
  1384.     ulNewValue = ulActualResistanceBitRate;
  1385. }
  1386.     }
  1387.  
  1388.     if(pASMSourceInfo->m_bTryToUpShift)
  1389.     {
  1390.      pASMSourceInfo->m_bTryToUpShift=FALSE;
  1391. //XXXRA why not check for ulNewValue < ((UINT32)(ulSourceBandwidth * 1.15)
  1392. // before assignment.  
  1393. ulNewValue = (UINT32)(ulSourceBandwidth * 1.15);
  1394.     }
  1395.     
  1396.     pASMSourceInfo->m_ulLastSetDelivery = ulNewValue;
  1397.     UINT32 ulActualRate = ulNewValue;
  1398.     /*
  1399.      * Always keep TCP traffic faster then needed
  1400.      * (but keep it quiet so the rest of the algorithm doesn't
  1401.      * find out :-)
  1402.      */
  1403.     if (pASMSourceInfo->m_TransportType == TNG_TCP)
  1404.     {
  1405. ulActualRate = MAX(ulActualRate,
  1406.     (UINT32)(ulSourceBandwidth * 1.10));
  1407.     }
  1408.     DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s, "(%p)Redist: Tranmission Rate to %d", pASMSourceInfo->m_pSource, ulActualRate));
  1409.                     if (m_bEnableSDB)
  1410.                     {
  1411.                         pThin->SetDeliveryBandwidth(ulActualRate, 0);
  1412.                     }
  1413.          if (bFastStart)
  1414.     {
  1415. pASMSourceInfo->m_pSource->m_turboPlayStats.ulAcceleratedBW = ulActualRate;
  1416.     }
  1417. }
  1418.     }
  1419. dont_actually_set_the_rate:
  1420.     HX_RELEASE(pThin);
  1421. }
  1422. m_State = HX_NONE;
  1423. return;
  1424.     }
  1425.     if (m_State == CHILL_BUFFERING)
  1426.     {
  1427. m_ulOfferToRecalc = lAggregateBandwidthUsage;
  1428. #ifdef MOREDEBUG
  1429. DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
  1430. "CHILL to Recalc() %d", m_ulOfferToRecalc));
  1431. #endif
  1432. m_State = HX_NONE;
  1433. Recalc();
  1434.     }
  1435.     if ((ulNumBehindSources) ||
  1436. ((lAggregateBandwidthUsage > ((INT32)m_ulMaxAccelBitRate + 100)) &&
  1437.     (bAllZeroBw)))
  1438.     {
  1439. if ((lAggregateBandwidthUsage > (INT32)m_ulMaxAccelBitRate) &&
  1440.     (bAllZeroBw))
  1441. {
  1442.     lAggregateBandwidthUsage = m_ulMaxAccelBitRate;
  1443. }
  1444. // XXXRA change m_ulNumReportsSinceUpShift to m_lNumReportsSinceUpShift
  1445. m_ulNumReportsSinceUpShift = -2;
  1446. UINT32 ulLow  = (UINT32)(m_ulLastStableBandwidth * 0.90);
  1447. UINT32 ulHigh = (UINT32)(m_ulLastStableBandwidth * 1.10);
  1448. /*
  1449.  * XXXSMP Maybe we don't want to use stable point when the aggregate
  1450.  * detected is more then the stable point?
  1451.  */
  1452. if ((lAggregateBandwidthUsage > (INT32)ulLow) && 
  1453.     (lAggregateBandwidthUsage < (INT32)ulHigh))
  1454. {
  1455.     /*
  1456.      * If we are close to the last stable bandwidth, then let's
  1457.      * try that one again.
  1458.      */
  1459.     lAggregateBandwidthUsage = m_ulLastStableBandwidth;
  1460. #ifdef MOREDEBUG
  1461.     DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
  1462. "Used Stable Point %d", m_ulLastStableBandwidth));
  1463. #endif
  1464.     m_ulLastStableBandwidth = 0;
  1465.     m_ulUpShiftTestPointScaleFactor = MAX(1500, 
  1466. (UINT32)(m_ulUpShiftTestPointScaleFactor * 0.85));
  1467. }
  1468. if (m_State != CONGESTION)
  1469. {
  1470.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  1471.     {
  1472. pASMSourceInfo = (ASMSourceInfo*)(*i);
  1473. UINT32 ulSourceBandwidth = pASMSourceInfo->m_ulSubscribedBw;
  1474. UINT32 ulNewValue = 
  1475. (UINT32)(
  1476. (float)ulSourceBandwidth /
  1477. (float)ulAggregateUsed *
  1478. (float)lAggregateBandwidthUsage * 0.97);
  1479. if (ulNewValue < (pASMSourceInfo->m_ulSubscribedBw))
  1480. {
  1481.     // Attempt ASM Switching to reduce bandwidth usage.
  1482.     m_State = CONGESTION;
  1483.     m_ulOfferToRecalc = (UINT32)
  1484.         (lAggregateBandwidthUsage * 0.97);
  1485. #ifdef MOREDEBUG
  1486.     DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
  1487. "CONGESTION to Recalc() %d", m_ulOfferToRecalc));
  1488. #endif
  1489.                     // once again, if we are in start start mode we need to 
  1490.                     // turn it off. It may be off already, but I just want to 
  1491.                     // make sure.
  1492.                     if (pASMSourceInfo->m_pSource->m_bFastStart)
  1493.                     {
  1494.                         DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,"(%p)ASM %d - Leaving TurboPlay", pASMSourceInfo->m_pSource, __LINE__));
  1495.                         pASMSourceInfo->m_pSource->LeaveFastStart(TP_OFF_BY_NETCONGESTION);
  1496.                     }
  1497.     Recalc();
  1498.     return;
  1499. }
  1500.     }
  1501.     m_State = CONGESTION;
  1502.     RecalcAccel();
  1503.     return;
  1504. } //m_State != CONGESTION
  1505. else
  1506. {
  1507.     BOOL bLossBehind = FALSE;
  1508.     m_State = HX_NONE;
  1509.     UINT32 ulTotalBandwidth = 0;
  1510.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  1511.     {
  1512. pASMSourceInfo = (ASMSourceInfo*)(*i);
  1513. IHXThinnableSource* pThin = 0;
  1514. UINT32 ulSourceBandwidth = pASMSourceInfo->m_ulSubscribedBw;
  1515. UINT32 ulNewValue = 
  1516. (UINT32)(
  1517. (float)ulSourceBandwidth /
  1518. (float)ulAggregateUsed *
  1519. (float)lAggregateBandwidthUsage * 0.70);
  1520. if (ulNewValue < ulSourceBandwidth)
  1521. {
  1522.     /* Can't be conservative, so go use what we need */
  1523.     ulNewValue = 
  1524.     (UINT32)(
  1525.     (float)ulSourceBandwidth /
  1526.     (float)ulAggregateUsed *
  1527.     (float)lAggregateBandwidthUsage * 0.97);
  1528.                     // once again, if we are in start start mode we need to 
  1529.                     // turn it off. It may be off already, but I just want to 
  1530.                     // make sure.
  1531.                     if (pASMSourceInfo->m_pSource->m_bFastStart)
  1532.                     {
  1533.                         DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,"(%p)ASM %d - Leaving TurboPlay", pASMSourceInfo->m_pSource, __LINE__));
  1534.                         pASMSourceInfo->m_pSource->LeaveFastStart(TP_OFF_BY_NETCONGESTION);
  1535.                     }
  1536. }
  1537. if (pASMSourceInfo->m_bLossBehind &&
  1538. (ulNewValue < ulSourceBandwidth))
  1539. {
  1540.     DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
  1541.     "(%p)No Loss Reduce: Will Force BP", pASMSourceInfo->m_pSource));
  1542.     ulNewValue = ulSourceBandwidth;
  1543. }
  1544. if ((HXR_OK == pASMSourceInfo->m_pSource->
  1545.     QueryInterface(IID_IHXThinnableSource, (void **)&pThin)))
  1546. {
  1547.     if (ulNewValue < (pASMSourceInfo->m_ulLastSetDelivery))
  1548.     {
  1549. DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
  1550.     "(%p)Congestion: Slow Tranmission Rate to %d %p", pASMSourceInfo->m_pSource,
  1551.     ulNewValue, pASMSourceInfo));
  1552. if (pASMSourceInfo->m_bLossBehind)
  1553. {
  1554.     pASMSourceInfo->m_ulIncomingBandwidth = ulNewValue;
  1555.     bLossBehind = TRUE;
  1556. }
  1557. if (pASMSourceInfo->m_ulRateBeforeDeAccel)
  1558. {
  1559.     pASMSourceInfo->m_ulRateBeforeDeAccel = ulNewValue;
  1560.     /*
  1561.      * Reset the core's acceleration status. 
  1562.      */
  1563.     IHXWatermarkBufferControl* pWMBufCtl = NULL;
  1564.     
  1565.     pASMSourceInfo->m_pSource->
  1566. QueryInterface(IID_IHXWatermarkBufferControl,
  1567.        (void**)&pWMBufCtl);
  1568.     if (pWMBufCtl)
  1569.     {
  1570. pWMBufCtl->ClearChillState();
  1571. pWMBufCtl->Release();
  1572. pWMBufCtl = NULL;
  1573.     }
  1574.     pASMSourceInfo->m_bMayBeAccelerated = TRUE;
  1575.     pASMSourceInfo->m_bPendingChill = FALSE;
  1576. }
  1577. if ((ulNewValue < ulSourceBandwidth) && (ulSourceBandwidth > 10))
  1578. {
  1579.     pASMSourceInfo->m_pSource->EnterBufferedPlay();
  1580. }
  1581. pASMSourceInfo->m_ulLastSetDelivery = ulNewValue;
  1582.         ulTotalBandwidth += ulNewValue;
  1583. UINT32 ulActualRate = ulNewValue;
  1584. /*
  1585.  * Always keep TCP traffic faster then needed
  1586.  * (but keep it quiet so the rest of the algorithm doesn't
  1587.  * find out :-)
  1588.  */
  1589. if (pASMSourceInfo->m_TransportType == TNG_TCP)
  1590. {
  1591.     ulActualRate = MAX(ulActualRate,
  1592. (UINT32)(ulSourceBandwidth * 1.10));
  1593. }
  1594.                         // In low heap mode, do not change the delivery bw.
  1595. // NOTE: There is concern that this is not 
  1596. // satisfactory as a truly long term solution since
  1597. // bw rate control is regarded by some as critical
  1598. // for limited resource platforms.
  1599. #if !defined(HELIX_CONFIG_LOW_HEAP_STREAMING)
  1600. pThin->SetDeliveryBandwidth(ulActualRate, 0);
  1601. #endif
  1602.     }
  1603.     else
  1604.     {
  1605.         ulTotalBandwidth +=
  1606.     pASMSourceInfo->m_ulLastSetDelivery;
  1607.     }
  1608. }
  1609. HX_RELEASE(pThin);
  1610.     }
  1611.     if (bLossBehind)
  1612.     {
  1613. m_ulNumReportsSinceUpShift = -10;
  1614. m_ulResistanceBitRate = MAX(15000, ulTotalBandwidth);
  1615. DEBUG_OUT(m_pEM, DOL_TRANSPORT, 
  1616.     (s, "Resistance Move %d", m_ulResistanceBitRate));
  1617.     }
  1618. }
  1619.     }
  1620.     else if (!ulNumSlightlyBehindSources)
  1621.     {
  1622. INT32 lAccelTestPoint;
  1623. double dRFactor = 1.05;
  1624. if ((INT32)m_ulUpShiftBandwidthAvail > lAggregateBandwidthUsage)
  1625. {
  1626.     lAccelTestPoint = (INT32) 
  1627. ((m_ulUpShiftBandwidthAvail - lAggregateBandwidthUsage)
  1628. * ((float)m_ulUpShiftTestPointScaleFactor / 10000.0)
  1629.     + lAggregateBandwidthUsage);
  1630. }
  1631. else
  1632. {
  1633.     lAccelTestPoint = lAggregateBandwidthUsage;
  1634. }
  1635. UINT32 ulAccelTestPoint =
  1636.     (lAccelTestPoint > 0) ? (UINT32)lAccelTestPoint : 0;
  1637. BOOL bResistanceLimited = FALSE;
  1638. BOOL bWentHigherThanResistanceRate = FALSE;
  1639. if (ulAccelTestPoint > m_ulMaxAccelBitRate)
  1640. {
  1641.     ulAccelTestPoint = m_ulMaxAccelBitRate;
  1642. }
  1643. if (ulAccelTestPoint > m_ulResistanceBitRate)
  1644. {
  1645.     UINT32 ulActualResistanceBitRate = m_ulResistanceBitRate;
  1646.     if (ulActualResistanceBitRate < ulAggregateUsed)
  1647.     {
  1648. ulActualResistanceBitRate = (UINT32)(ulAggregateUsed * 1.05);
  1649.     }
  1650.     UINT32 ulOldAccelTestPoint = ulAccelTestPoint;
  1651.     if (ulAccelTestPoint > ulActualResistanceBitRate)
  1652.     {
  1653. UINT32 bHowManyReports =
  1654.     (ulActualResistanceBitRate <
  1655.       ulTotalMaxSubscribedBw) ? 5 : 10;
  1656. if (m_ulUpShiftPastResistanceCount > bHowManyReports)
  1657. {
  1658.     bWentHigherThanResistanceRate = TRUE;
  1659.     if ((m_ulOriginalResistanceBitRate >
  1660.         ulActualResistanceBitRate) &&
  1661. (ulActualResistanceBitRate < ulTotalMaxSubscribedBw))
  1662.     {
  1663. dRFactor = (ulActualResistanceBitRate +
  1664.     ((m_ulOriginalResistanceBitRate -
  1665.     ulActualResistanceBitRate) * 0.10)) /
  1666.     (double)ulActualResistanceBitRate;
  1667. if (dRFactor < 1.01)
  1668. {
  1669.     dRFactor = 1.01;
  1670. }
  1671. #ifdef MOREDEBUG
  1672.         DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
  1673.     "Resistance Accel Factor %0.2f", dRFactor));
  1674. #endif
  1675.     }
  1676.     else
  1677.     {
  1678. dRFactor = 1.01;
  1679.     }
  1680.       ulAccelTestPoint = (UINT32)(ulActualResistanceBitRate *
  1681.         dRFactor);
  1682. }
  1683. else
  1684. {
  1685.     ulAccelTestPoint = ulActualResistanceBitRate;
  1686. }
  1687. if (ulOldAccelTestPoint < ulAccelTestPoint)
  1688. {
  1689.     ulAccelTestPoint = ulOldAccelTestPoint;
  1690. }
  1691. else
  1692. {
  1693.     bResistanceLimited = TRUE;
  1694. }
  1695.     }
  1696. }
  1697. if ((m_ulNumReportsSinceUpShift >= 2) &&
  1698. ((INT32)m_ulHighestBandwidthAvail < lAggregateBandwidthUsage))
  1699. {
  1700.     m_ulHighestBandwidthAvail = lAggregateBandwidthUsage;
  1701.     m_ulPeakUsedBandwidth = lAggregateBandwidthUsage;
  1702.     m_bInitialHighBwAvail = FALSE;
  1703. }
  1704. DEBUG_OUT(m_pEM, DOL_TRANSPORT_EXTENDED,
  1705.     (s, "UP Bw Report: Num=%d, Avail=%d, CurrentBw=%d, TestPoint=%d", 
  1706.     m_ulNumReportsSinceUpShift, m_ulUpShiftBandwidthAvail,
  1707.     lAggregateBandwidthUsage, ulAccelTestPoint));
  1708. BOOL bDidChange = FALSE;
  1709. BOOL bBrokeMax = FALSE;
  1710. if ((m_ulNumReportsSinceUpShift >= 2) &&
  1711.     (INT32) (ulAccelTestPoint) > lAggregateBandwidthUsage)
  1712. {
  1713.     m_ulLastStableBandwidth = lAggregateBandwidthUsage;
  1714.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  1715.     {
  1716. pASMSourceInfo = (ASMSourceInfo*)(*i);
  1717. IHXThinnableSource* pThin = 0;
  1718. UINT32 ulSourceBandwidth = pASMSourceInfo->m_ulSubscribedBw;
  1719. UINT32 ulNewValue = 
  1720. (UINT32)(
  1721. (float)ulSourceBandwidth /
  1722. (float)ulAggregateUsed *
  1723. (float)ulAccelTestPoint);
  1724. if (ulNewValue > (pASMSourceInfo->m_ulMaxSubscribedBw * 4))
  1725. {
  1726.     ulNewValue = (UINT32) 
  1727. (pASMSourceInfo->m_ulMaxSubscribedBw * 4);
  1728. }
  1729. /*
  1730.  * Live streams get capped at 107% of Max to prevent 
  1731.  * unneeded bandwidht modulation.
  1732.  */
  1733. if ((pASMSourceInfo->m_pSource->IsLive()) &&
  1734.    (ulNewValue >
  1735. (pASMSourceInfo->m_ulMaxSubscribedBw * 1.07)))
  1736. {
  1737.     ulNewValue = (UINT32)
  1738. (pASMSourceInfo->m_ulMaxSubscribedBw * 1.07);
  1739. }
  1740. if ((ulNewValue > (pASMSourceInfo->m_ulMaxSubscribedBw)) &&
  1741.     (ulNewValue > (ulSourceBandwidth * 3)) &&
  1742.     (pASMSourceInfo->m_ulLastSetDelivery <
  1743. pASMSourceInfo->m_ulMaxSubscribedBw))
  1744. {
  1745.     /*
  1746.      * If we are already accelerating 3x subscribed bandwidth
  1747.      * and we are about to upshift beyond the max possible
  1748.      * bandwidth, then let's stop and take a breather just
  1749.      * above the max subscription.  This prevents us from
  1750.      * buffering huge amounts of the crappy low bw stream.
  1751.      */
  1752.     UINT32 ulTemp;
  1753.     ulTemp = (UINT32) 
  1754. (pASMSourceInfo->m_ulMaxSubscribedBw * 1.10);
  1755.     ulNewValue = MIN(ulTemp, ulNewValue);
  1756. }
  1757. if (pASMSourceInfo->m_ulLastSetDelivery >
  1758. pASMSourceInfo->m_ulMaxSubscribedBw)
  1759. {
  1760.     bBrokeMax = TRUE;
  1761. }
  1762. if (pASMSourceInfo->m_bMayBeAccelerated &&
  1763.    (HXR_OK == pASMSourceInfo->m_pSource->
  1764.     QueryInterface(IID_IHXThinnableSource, (void **)&pThin)))
  1765. {
  1766.     double Factor;
  1767.     if (bResistanceLimited)
  1768.     {
  1769. Factor = 1.005;
  1770.     }
  1771.     else if (pASMSourceInfo->m_pSource->IsLive())
  1772.     {
  1773. Factor = 1.01;
  1774.     }
  1775.     else
  1776.     {
  1777. Factor = 1.05;
  1778.     }
  1779.     if ((ulNewValue > (pASMSourceInfo->m_ulLastSetDelivery * Factor)) && 
  1780. pASMSourceInfo->m_bSourceAccelAllowed)
  1781.     {
  1782. DEBUG_OUT(m_pEM, DOL_TRANSPORT, 
  1783. (s, "(%p)Accelerating: NewTransmissionRate=%d", pASMSourceInfo->m_pSource, ulNewValue));
  1784. m_ulUpShiftPastResistanceCount = 0;
  1785. if (ulNewValue > ulSourceBandwidth)
  1786. {
  1787.     pASMSourceInfo->m_pSource->LeaveBufferedPlay();
  1788. }
  1789. bDidChange = TRUE;
  1790. /*
  1791.  * WHOA!  If this is a timestamp delivered source
  1792.  * i.e. 5.0 thinning, then the imperical Getbandwidth()
  1793.  * will never reach the rate that we set, so we help
  1794.  * it along a bit (just a bit of a nudge, eh?).
  1795.  */
  1796. if (pASMSourceInfo->m_bTimeStampDelivery)
  1797. {
  1798.     pASMSourceInfo->m_ulIncomingBandwidth = ulNewValue;
  1799. }
  1800. m_ulNumReportsSinceUpShift = 0;
  1801. pASMSourceInfo->m_bInvalidUpReport = TRUE;
  1802. m_bDidOfferUpShiftToRecalc = FALSE;
  1803. pThin->SetDeliveryBandwidth(
  1804.     (pASMSourceInfo->m_ulLastSetDelivery = ulNewValue), 0);
  1805.     }
  1806. }
  1807. HX_RELEASE(pThin);
  1808.     }
  1809. }
  1810. if ((bDidChange == TRUE) && (bWentHigherThanResistanceRate))
  1811. {
  1812.     m_ulResistanceBitRate = (UINT32)(m_ulResistanceBitRate * dRFactor);
  1813.     DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
  1814.         "Went over ResistanceBitRate %d", m_ulResistanceBitRate));
  1815. }
  1816. if (((bDidChange == FALSE) &&
  1817.     (m_ulNumReportsSinceUpShift > NUM_REPORTS_NEEDED_TO_UPSHIFT) ||
  1818.     (bBrokeMax == TRUE)) && (m_bDidOfferUpShiftToRecalc == FALSE))
  1819. {
  1820.     m_State = HX_NONE;
  1821.     m_bDidOfferUpShiftToRecalc = TRUE;
  1822.     m_ulOfferToRecalc = lAggregateBandwidthUsage;
  1823. #ifdef MOREDEBUG
  1824.     DEBUG_OUT(m_pEM, DOL_TRANSPORT, (s,
  1825. "Upshift Offer to Recalc() %d", m_ulOfferToRecalc));
  1826. #endif
  1827.     Recalc();
  1828.     return;
  1829. }
  1830.     }
  1831. }
  1832. void
  1833. ASMStreamInfo::NotifyNewBandwidth()
  1834. {
  1835.     m_pNegotiator->SetBandwidthUsage(m_ulLastBandwidth,
  1836. m_bTimeStampDelivery);
  1837. }
  1838. void
  1839. ASMStreamInfo::NotifyTimeStampDelivery()
  1840. {
  1841.     if(m_bTimeStampDelivery)
  1842.     {
  1843. m_pASMSourceInfo->m_bTimeStampDelivery = TRUE;
  1844.     }
  1845. }
  1846. UINT32
  1847. ASMSourceInfo::GetBandwidth()
  1848. {
  1849.     return m_ulIncomingBandwidth;
  1850. }
  1851. void
  1852. ASMStreamInfo::SetLastBandwidth(UINT32 ulOffer)
  1853. {
  1854.     m_ulLastBandwidth = ulOffer;
  1855. }
  1856. void
  1857. ASMStreamInfo::NotifyLimitBandwidth(UINT32 ulRecv)
  1858. {
  1859.     if(m_pASMSourceInfo->m_bBehind)
  1860.     {
  1861. m_pNegotiator->HandleSlowSource(ulRecv);
  1862.     }
  1863. }
  1864. ASMSourceInfo::ASMSourceInfo(HXSource* pSource, HXSM* pHXASM)
  1865.     : m_ulLastReportTime(0)
  1866.     , m_ulIncomingBandwidth(0)
  1867.     , m_ulRateBeforeDeAccel(0)
  1868.     , m_lTimeDiffBase(0)
  1869.     , m_ulBytesBehind(0)
  1870.     , m_lLastBehindTime(0)
  1871.     , m_ulLastSetDelivery(0xffffffff)
  1872.     , m_ulSubscribedBw(0)
  1873.     , m_ulMaxSubscribedBw(0)
  1874.     , m_bBehind(FALSE)
  1875.     , m_bLossBehind(FALSE)
  1876.     , m_bSlightlyBehind(FALSE)
  1877.     , m_bTimeStampDelivery(FALSE)
  1878.     , m_bPendingChill(FALSE)
  1879.     , m_bInvalidUpReport(FALSE)
  1880.     , m_bPerfectPlay(FALSE)
  1881.     , m_bIsDone(FALSE)
  1882.     , m_bMayBeAccelerated(TRUE)
  1883.     , m_bTryToUpShift(FALSE)
  1884.     , m_bAdjustBandwidth(FALSE)
  1885.     , m_ulLowestBandwidthBeforeTimeStamp(0)
  1886.     , m_bSourceAccelAllowed(TRUE)
  1887.     , m_bSourceDecelAllowed (TRUE)
  1888.     , m_bSlidingBwWindowReady(FALSE)
  1889.     , m_pMasterRuleBook(0)
  1890.     , m_pStreams(0)
  1891.     , m_TransportType(TNG_UDP)
  1892.     , m_pSource(pSource)
  1893.     , m_pSBI(0)
  1894.     , THRESHOLD(1000)
  1895.     , m_lRefCount(0)
  1896.     , m_ulBwDetectionDataCount(0)
  1897.     , m_ulBwDetectionDataLen(0)
  1898.     , m_ulSlidingWindowLocation(0)
  1899.     , m_pBwDetectionData(NULL)
  1900.     , m_pHXASM(pHXASM)
  1901. {
  1902.     m_lOuterThreshold = THRESHOLD;
  1903.     IHXValues* pHeader = 0;
  1904.     pSource->AddRef();
  1905.     if (pSource->m_pFileHeader)
  1906.     {
  1907. IHXBuffer* pMasterRuleBook = NULL;
  1908. pSource->m_pFileHeader->
  1909.     GetPropertyCString("ASMRuleBook", pMasterRuleBook);
  1910. if (pMasterRuleBook)
  1911. {
  1912.     m_pMasterRuleBook = new ASMRuleBook
  1913. ((const char *)pMasterRuleBook->GetBuffer());
  1914. }
  1915. HX_RELEASE(pMasterRuleBook);
  1916.     }
  1917. }
  1918. ASMSourceInfo::~ASMSourceInfo()
  1919. {
  1920.     HX_VECTOR_DELETE(m_pBwDetectionData);
  1921.     delete[] m_pStreams;
  1922.     delete m_pMasterRuleBook;
  1923. }
  1924. BOOL
  1925. ASMSourceInfo::AllocBWDetectionData(UINT32 ulReqSize)
  1926. {
  1927.     BOOL bOk = TRUE;
  1928.     // Our current array is too small
  1929.     if (ulReqSize > m_ulBwDetectionDataLen)
  1930.     {
  1931. BwDetectionData* pTemp = new BwDetectionData[ulReqSize];
  1932. if (!pTemp)
  1933. {
  1934.     bOk = FALSE;
  1935. }
  1936. else
  1937. {
  1938.     if (m_pBwDetectionData)
  1939.     {
  1940. memcpy(pTemp, m_pBwDetectionData, m_ulBwDetectionDataLen * sizeof(BwDetectionData)); /* Flawfinder: ignore */
  1941. HX_VECTOR_DELETE(m_pBwDetectionData);
  1942.     }
  1943.     m_pBwDetectionData = pTemp;
  1944.     m_ulBwDetectionDataLen = ulReqSize;
  1945. }
  1946.     }
  1947.     return bOk;
  1948. }
  1949. void
  1950. ASMSourceInfo::Done()
  1951. {
  1952.     HX_RELEASE(m_pSBI);
  1953.     HX_RELEASE(m_pSource);
  1954.     m_bIsDone = TRUE;
  1955. }
  1956. STDMETHODIMP_(UINT32)
  1957. ASMSourceInfo::AddRef(void)
  1958. {
  1959.     return InterlockedIncrement(&m_lRefCount);
  1960. }
  1961. STDMETHODIMP_(UINT32)
  1962. ASMSourceInfo::Release(void)
  1963. {
  1964.     if (InterlockedDecrement(&m_lRefCount) > 0)
  1965.     {
  1966. return m_lRefCount;
  1967.     }
  1968.     delete this;
  1969.     return 0;
  1970. }
  1971. STDMETHODIMP
  1972. ASMSourceInfo::QueryInterface
  1973. (
  1974.     REFIID interfaceID,
  1975.     void** ppInterfaceObj
  1976. )
  1977. {
  1978.     QInterfaceList qiList[] =
  1979.         {
  1980.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)this },
  1981.             { GET_IIDHANDLE(IID_IHXBandwidthManagerInput), (IHXBandwidthManagerInput*)this },
  1982.         };
  1983.     
  1984.     return ::QIFind(qiList, QILISTSIZE(qiList), interfaceID, ppInterfaceObj);
  1985. }
  1986. STDMETHODIMP
  1987. ASMSourceInfo::ReportDataPacket
  1988. (
  1989.     UINT32 ulTimeStamp,
  1990.     UINT32 ulArrivedTimeStamp,
  1991.     UINT32 ulSize
  1992. )
  1993. {
  1994.     if (m_bIsDone)
  1995.     {
  1996. return HXR_OK;
  1997.     }
  1998.     UINT32 ulCurrentTime = HX_GET_TICKCOUNT();
  1999.     if (!m_pHXASM->m_ulNextPacketWindow)
  2000.     {
  2001. m_pHXASM->m_ulNextPacketWindow = ulCurrentTime;
  2002.     }
  2003.     if (ulSize == REPORT_DATA_PACKET_LOST)
  2004.     {
  2005.         ULONG32 ulNumLost = ulArrivedTimeStamp-ulTimeStamp+1;
  2006. //XXXgfw Don't allow Decel if this is a load test.....
  2007. if (m_bSourceDecelAllowed)
  2008. {
  2009.             m_pHXASM->m_lLoss += ulNumLost;    
  2010. }
  2011.         m_pHXASM->m_lPacketCounter += ulNumLost;
  2012. return HXR_OK;
  2013.     }
  2014.     m_pHXASM->m_lPacketCounter++;
  2015.     // Make sure we have a buffer for bandwidth detection!
  2016.     if (!m_pBwDetectionData)
  2017.     {
  2018. //XXXNH: SMP pulled these numbers out of his hat, so let's
  2019. // stick with them for now.
  2020. UINT32 uEstSize = m_TransportType == TNG_TCP ? 300 : 20;
  2021. if (!AllocBWDetectionData(uEstSize))
  2022.     return HXR_OUTOFMEMORY;
  2023.     }
  2024.     if (CALCULATE_ELAPSED_TICKS(m_pHXASM->m_ulNextPacketWindow,
  2025.      ulCurrentTime) > 3000)
  2026.     {
  2027. m_pHXASM->m_ulNextPacketWindow = ulCurrentTime;
  2028. UINT32 ulLossPercentage = (UINT32)(
  2029.     100 * (float)m_pHXASM->m_lLoss / (float)m_pHXASM->m_lPacketCounter);
  2030. #ifdef MOREDEBUG
  2031. DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT, (s, "(%p)Loss %d", m_pSource, ulLossPercentage));
  2032. #endif
  2033. /* Don't do anything unless we have 4% Loss */
  2034. BOOL bDeAccel = (ulLossPercentage >= 4);
  2035. /* Cut down bandwidth usage ONLY if it won't cause a downshift */
  2036. bDeAccel = bDeAccel &&
  2037. (m_ulLastSetDelivery * 0.95 > m_ulSubscribedBw);
  2038. /* Don't throttle back if we're in chill acc buffering */
  2039. bDeAccel = bDeAccel && (m_ulRateBeforeDeAccel == 0);
  2040. /* If Loss is over 20%, always throttle back */
  2041. bDeAccel = bDeAccel || (ulLossPercentage >= 20);
  2042. if (bDeAccel)
  2043. {
  2044.     if (ulLossPercentage >= 20)
  2045.     {
  2046. /* 
  2047.  * make sure to never go into timestamp delivery/keyframe mode
  2048.  * due to loss
  2049.  */
  2050.         m_ulIncomingBandwidth = (UINT32) MAX(m_ulLastSetDelivery * 0.85, 
  2051. m_ulLowestBandwidthBeforeTimeStamp * 1.05);
  2052.     }
  2053.     else
  2054.     {
  2055. if (ulLossPercentage > 15)
  2056. {
  2057.     ulLossPercentage = 15;
  2058. }
  2059.         
  2060. // do not change subscription due to "less than 20% loss"
  2061. m_ulIncomingBandwidth = (UINT32) MAX(m_ulLastSetDelivery *
  2062.     (1 - (ulLossPercentage / (float)100)),
  2063.     m_ulSubscribedBw * 1.05);
  2064.     }
  2065.             if (m_pSource->m_bFastStart)
  2066.             {
  2067.                 DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT, (s,"(%p)ASM %d - Leaving TurboPlay", m_pSource, __LINE__));
  2068.                 m_pSource->LeaveFastStart(TP_OFF_BY_NETCONGESTION);
  2069.                 if (m_ulIncomingBandwidth > m_ulMaxSubscribedBw * 1.05)
  2070.                 {
  2071.                     m_ulIncomingBandwidth = m_ulMaxSubscribedBw * 1.05;
  2072.                 }
  2073.             }
  2074.     m_bLossBehind = TRUE;
  2075.     DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT, (s, "(%p)Lower Loss %d", m_pSource, m_ulIncomingBandwidth));
  2076.     /* Signal Recalc to adjust the highest available bandwidth */
  2077.     m_pHXASM->m_bPipeFull = TRUE;
  2078.     m_bBehind = TRUE;
  2079.     m_pHXASM->RecalcAccel();
  2080.     m_bBehind = FALSE;
  2081.     m_bLossBehind = FALSE;
  2082. }
  2083. else if (ulLossPercentage <= 1)
  2084. {
  2085.     m_pHXASM->m_ulUpShiftPastResistanceCount++;
  2086. }
  2087. if (ulLossPercentage > 2)
  2088. {
  2089.     m_pHXASM->m_ulUpShiftPastResistanceCount = 0;
  2090. }
  2091. m_pHXASM->m_lLoss = 0;
  2092. m_pHXASM->m_lPacketCounter = 0;
  2093.     }
  2094.     if (m_bSlidingBwWindowReady)
  2095.     {
  2096. //INT32 i;
  2097. UINT32 ulPrevLocation = m_ulSlidingWindowLocation;
  2098. /*
  2099.  *  Set the data for the current packet
  2100.  */
  2101. m_pBwDetectionData[m_ulSlidingWindowLocation].
  2102.     m_ulSize     = ulSize;
  2103. m_pBwDetectionData[m_ulSlidingWindowLocation].
  2104.     m_ulTimeStamp     = ulTimeStamp;
  2105. m_pBwDetectionData[m_ulSlidingWindowLocation].
  2106.     m_ulATime     = ulArrivedTimeStamp;
  2107. m_ulSlidingWindowLocation++;
  2108. /*
  2109.  * wrap around if at the end
  2110.  */
  2111. if (m_ulSlidingWindowLocation == m_ulBwDetectionDataCount)
  2112. {
  2113.     m_ulSlidingWindowLocation = 0;
  2114. }
  2115. /*
  2116.  * count up all data for the whole window
  2117.  */
  2118. //UINT32 ulWindowSize = 0;
  2119. //for (i = 0; i < m_ulBwDetectionDataCount; i++)
  2120. //{
  2121. //    ulWindowSize += m_pBwDetectionData[i].m_ulSize;
  2122. //}
  2123. /*
  2124.  *  m_ulSlidingWindowLocation now points to the very first
  2125.  *  info in the window.  Take the diff in time from the data
  2126.  *  that we just entered (ulPrevLocation) and the time of the
  2127.  *  first data.
  2128.  */
  2129. //UINT32 ulWindowRealTime = m_pBwDetectionData[ulPrevLocation].m_ulATime
  2130. //    - m_pBwDetectionData[m_ulSlidingWindowLocation].m_ulATime;
  2131. /*
  2132.  *  Calculate bandwidth for the window in bytes * 8 / millis.
  2133.  *  I have no idea why it is bytes * 8. //XXXPM?
  2134.  *  If we are in constant bitrate mode, then this calculated
  2135.  *  bitrate will be compared to the constant bitrate.  If we
  2136.  *  are not in constant bitrate mode, then this calculated
  2137.  *  bitrate will be compared to the bitrate coming from the
  2138.  *  bandwidth reports.
  2139.  */
  2140. //m_ulLastBandwidthReport = (UINT32) (ulWindowSize * 8 /
  2141. //    ((ulWindowRealTime) / 1000.0));
  2142. // This is the short-term bandwidth count (sans buffering fudge)
  2143.     }
  2144.     else
  2145.     {
  2146. m_pBwDetectionData[m_ulBwDetectionDataCount].
  2147.     m_ulSize     = ulSize;
  2148. m_pBwDetectionData[m_ulBwDetectionDataCount].
  2149.     m_ulTimeStamp     = ulTimeStamp;
  2150. m_pBwDetectionData[m_ulBwDetectionDataCount].
  2151.     m_ulATime     = ulArrivedTimeStamp;
  2152. if(m_TransportType == TNG_TCP)
  2153. {
  2154.     if(((m_pBwDetectionData[m_ulBwDetectionDataCount].m_ulTimeStamp -
  2155. m_pBwDetectionData[0].m_ulTimeStamp > 30000) &&
  2156. m_ulBwDetectionDataCount > 300))
  2157.     {
  2158. m_bSlidingBwWindowReady = TRUE;
  2159.     }
  2160. }
  2161. else if(m_TransportType == TNG_UDP)
  2162. {
  2163.     if (((((m_pBwDetectionData[m_ulBwDetectionDataCount].m_ulTimeStamp -
  2164.         m_pBwDetectionData[0].m_ulTimeStamp) > 3000) &&
  2165.         (m_ulBwDetectionDataCount > 20)) ||
  2166.        (m_pBwDetectionData[m_ulBwDetectionDataCount].m_ulATime -
  2167.         m_pBwDetectionData[0].m_ulATime > 3000)))
  2168.     // XXXSMP Re-examine this formula later.
  2169.     {
  2170.         m_bSlidingBwWindowReady = TRUE;
  2171.     }
  2172. }
  2173. if(!m_bSlidingBwWindowReady)
  2174. {
  2175.     m_ulBwDetectionDataCount++;
  2176.     // do we not have a big enough buffer for calculating bandwidth?
  2177.     if (m_ulBwDetectionDataCount >= m_ulBwDetectionDataLen)
  2178.     {
  2179. // if we already have at least 1024 data points or we are 
  2180. // out of memory then we'll just have to make do
  2181. UINT32 ulNewSize = m_ulBwDetectionDataLen * 2;
  2182. UINT32 ulMaxSize = min(BW_DETECTION_DATA_POINTS, ulNewSize);
  2183. if (m_ulBwDetectionDataLen >= BW_DETECTION_DATA_POINTS ||
  2184.     !AllocBWDetectionData(ulMaxSize))
  2185. {
  2186.     m_ulBwDetectionDataCount--;
  2187.     m_bSlidingBwWindowReady = TRUE;
  2188. }
  2189.     }
  2190. }
  2191.     }
  2192.     return HXR_OK;
  2193. }
  2194. UINT32
  2195. ASMSourceInfo::GetBandwidthSince(UINT32 ulTime,
  2196.      UINT32 ulNow)
  2197. {
  2198.     if (m_bIsDone)
  2199.     {
  2200. return HXR_OK;
  2201.     }
  2202.     /*
  2203.      *  If we have not seen enough yet to get an idea.
  2204.      */
  2205.     if(!m_bSlidingBwWindowReady)
  2206.     {
  2207. //XXXPM Hack this in to make TCP do small window calcs
  2208. if(m_pBwDetectionData && m_TransportType == TNG_TCP &&
  2209. (m_pBwDetectionData[m_ulBwDetectionDataCount].m_ulTimeStamp -
  2210. m_pBwDetectionData[0].m_ulTimeStamp > 1000))
  2211. {
  2212.     /* XXXPM, Disgusting */
  2213.     goto tcphackedin;
  2214. }
  2215. return 0;
  2216.     }
  2217. tcphackedin:
  2218.     UINT32 i;
  2219.     UINT32 sane = m_ulSlidingWindowLocation;
  2220.     UINT32 ulCount = 0;
  2221.     if(m_ulSlidingWindowLocation == 0)
  2222.     {
  2223. i = m_ulBwDetectionDataCount - 1;
  2224.     }
  2225.     else
  2226.     {
  2227. i = m_ulSlidingWindowLocation - 1;
  2228.     }
  2229.     UINT32 ulLastTime = ulNow;
  2230.     /*
  2231.      * add up the data size for all packets since ulTime
  2232.      */
  2233.     while(m_pBwDetectionData[i].m_ulATime > ulTime)
  2234.     {
  2235. ulCount += m_pBwDetectionData[i].m_ulSize;
  2236. /*
  2237.  * remember the time of this packet so that we can calculate duration
  2238.  */
  2239. ulLastTime = m_pBwDetectionData[i].m_ulATime; 
  2240. if(i == 0)
  2241. {
  2242.     i = m_ulBwDetectionDataCount - 1;
  2243. }
  2244. else
  2245. {
  2246.     i--;
  2247. }
  2248. if(i == sane)
  2249. {
  2250.     //XXXPM we have travelled all the way around the window
  2251.     //and still don't have enough.
  2252.     break;
  2253. }
  2254.     }
  2255.     if (ulNow == ulLastTime)
  2256.     {
  2257. return 0;
  2258.     }
  2259.     return (UINT32)((ulCount * 8) / ((ulNow - ulLastTime) / 1000.0));
  2260. }
  2261. STDMETHODIMP
  2262. ASMSourceInfo::ReportUpshiftInfo(UINT32 ulTimeStamp,
  2263.      UINT32 ulSize)
  2264. {
  2265.     // In low heap mode, skip this because it causes the server to alter the
  2266.     // transmission rate. NOTE: technically this is the similar change in
  2267.     // ReportLatency should disable surestream stream switching, but in
  2268.     // testing this is not born out.
  2269. #if defined(HELIX_CONFIG_LOW_HEAP_STREAMING)
  2270.     return HXR_OK;
  2271. #endif
  2272.     if (m_bIsDone)
  2273.     {
  2274. return HXR_OK;
  2275.     }
  2276.     if (m_TransportType == TNG_TCP)
  2277. return HXR_OK;
  2278.     m_pHXASM->UpShiftInfo(ulTimeStamp, ulSize);
  2279.     return HXR_OK;
  2280. }
  2281. void
  2282. HXSM::UpShiftInfo(UINT32 ulTimeStamp, UINT32 ulSize)
  2283. {
  2284.     UINT32 ulT = 1;
  2285.     UINT32 ulS = 0;
  2286.     m_ulUpShiftTimes[m_ulUpShiftRingPos] = ulTimeStamp;
  2287.     m_ulUpShiftSizes[m_ulUpShiftRingPos] = ulSize;
  2288.     m_ulUpShiftRingPos++;
  2289.     if (m_ulUpShiftRingPos == 5)
  2290.     {
  2291. m_ulUpShiftRingPos = 0;
  2292. m_bUpShiftInfoReady = TRUE;
  2293.     }
  2294.     if (m_bUpShiftInfoReady)
  2295.     {
  2296. for (int i = 0; i < 5; i++)
  2297. {
  2298.     /*
  2299.      * XXXSMP We should:
  2300.      * Weight each BackToBack timing by the size of the packet
  2301.      * it timed, because timing larger packets is more accurate.
  2302.      */
  2303.     ulT += m_ulUpShiftTimes[i];
  2304.     ulS += m_ulUpShiftSizes[i];
  2305. }
  2306.     }
  2307.     if (ulT < 50)
  2308.     {
  2309. ulT = (UINT32) (ulT * 1.2); // The clock is not very accurate.
  2310. if (ulT > 50)
  2311.     ulT = 50;
  2312.     }
  2313.     if (m_bUpShiftInfoReady)
  2314.     {
  2315. /* Use 5ms padding for good luck */
  2316. m_ulUpShiftBandwidthAvail = ulS * 8000 / (ulT + 5);
  2317.     }
  2318.     else
  2319.     {
  2320. /* Use 40-60ms padding if we are counting on one info item only */
  2321. if (ulSize > 500)
  2322.     m_ulUpShiftBandwidthAvail = ulSize * 8000 / (ulTimeStamp + 40);
  2323. else
  2324.     m_ulUpShiftBandwidthAvail = ulSize * 8000 / (ulTimeStamp + 60);
  2325.     }
  2326.     RecalcAccel();
  2327. }
  2328. HX_RESULT
  2329. ASMSourceInfo::ReportLatency(UINT32 ulServerTime,
  2330.      UINT32 ulClientTime)
  2331. {
  2332.     // In low heap mode, skip this because it causes the server to alter the
  2333.     // transmission rate. NOTE: technically this is the similar change in
  2334.     // ReportUpShiftInfo should disable surestream stream switching, but in
  2335.     // testing this is not born out.
  2336. #if defined(HELIX_CONFIG_LOW_HEAP_STREAMING)
  2337.     return HXR_OK;
  2338. #endif
  2339.     if (m_bIsDone)
  2340.     {
  2341. return HXR_OK;
  2342.     }
  2343.     INT32 lBackedUp;
  2344.     lBackedUp = CalcBackup(ulServerTime, ulClientTime);
  2345.     INT32 lDetectedBandwidth;
  2346.     if(m_TransportType == TNG_UDP)
  2347.     {
  2348. UINT32 ulTemp = MAX(800, 4000 - m_lOuterThreshold);
  2349. UINT32 ulStartWindow = ulClientTime - ulTemp;
  2350. lDetectedBandwidth = GetBandwidthSince(ulStartWindow, ulClientTime);
  2351.     }
  2352.     else
  2353.     {
  2354. lDetectedBandwidth = GetBandwidthSince(ulClientTime -
  2355. TCP_BANDWIDTH_WINDOW, ulClientTime);
  2356.     }
  2357.     /*
  2358.      *  The THRESHOLD window is from THRESHOLD to m_lOuterThreshold.
  2359.      *  Once we go over threshold, we recalc the bandwidth and will do
  2360.      *  something to slow things down in m_pHXASM->Recalc.  We don't
  2361.      *  want to recalc the bandwidth again until we catch up to THRESHOLD
  2362.      *  or get slower again.  This is so that when we send one LimitBandwidth
  2363.      *  message we don't send another just when we are catching up (because
  2364.      *  sometimes during this time we can receive less and less data.)
  2365.      */
  2366.     //XXXgfw Don't allow Decel if this is a load test.....
  2367.     if ((lBackedUp >= (INT32)THRESHOLD) && (m_bSourceDecelAllowed))
  2368.     {
  2369. /*
  2370.  *  If we are backed up over our threshold window, then resize the
  2371.  *  window and recalc our bandwidth.
  2372.  */
  2373. if ((lBackedUp > m_lOuterThreshold) &&
  2374.     ((lDetectedBandwidth < (INT32)m_ulIncomingBandwidth) || 
  2375. (!m_ulIncomingBandwidth)))
  2376. {
  2377.     m_ulIncomingBandwidth = lDetectedBandwidth;
  2378.     /* Signal Recalc to adjust the highest available bandwidth */
  2379.     m_pHXASM->m_bPipeFull = TRUE;
  2380.     m_lOuterThreshold = lBackedUp + 500;
  2381. }
  2382. /*
  2383.  * This can either grow or shrink the threshold window.
  2384.  */
  2385. m_bBehind = TRUE;
  2386. m_bSlightlyBehind = TRUE;
  2387.     }
  2388.     else 
  2389.     {
  2390. m_lOuterThreshold = THRESHOLD;
  2391. m_bBehind = FALSE;
  2392. UINT ulNew = 0;
  2393. //XXXgfw Don't allow Decel if this is a load test.....
  2394. if ((lBackedUp > 400) && (m_bSourceDecelAllowed))
  2395.     m_bSlightlyBehind = TRUE;
  2396. else
  2397. {
  2398.     m_bSlightlyBehind = FALSE;
  2399.     if (m_TransportType == TNG_TCP)
  2400.     {
  2401. DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT,
  2402.     (s, "(%p)TCP Shift up = %d", m_pSource,
  2403.     m_pHXASM->m_ulUpShiftBandwidthAvail));
  2404. m_pHXASM->m_ulUpShiftBandwidthAvail = MAX(
  2405.     m_pHXASM->m_ulUpShiftBandwidthAvail,
  2406.     (UINT32)(lDetectedBandwidth * 1.5));
  2407.     }
  2408. }
  2409. if (m_bInvalidUpReport)
  2410. {
  2411.     m_bInvalidUpReport = FALSE;
  2412.     m_ulLastReportTime = ulClientTime;
  2413.     return HXR_OK;
  2414. }
  2415. UINT32 ulTemp = MAX(m_ulRateBeforeDeAccel, m_ulLastSetDelivery);
  2416. if ((lDetectedBandwidth > (INT32)ulTemp) ||
  2417.     (!m_ulIncomingBandwidth))
  2418.     ulNew = ulTemp + 1;
  2419. else
  2420.     ulNew = lDetectedBandwidth;
  2421. if (ulNew > m_ulIncomingBandwidth)
  2422. {
  2423.     m_ulIncomingBandwidth = ulNew;
  2424. }
  2425.     }
  2426.     m_ulLastReportTime = ulClientTime;
  2427.     m_pHXASM->m_ulNumReportsSinceUpShift++;
  2428.     if (m_bPendingChill)
  2429.     {
  2430. m_bPendingChill = FALSE;
  2431. m_pHXASM->m_State = HXSM::CHILL_BUFFERING;
  2432. m_pHXASM->RecalcAccel();
  2433. IHXThinnableSource* pThin = NULL;
  2434. if ((HXR_OK == m_pSource->
  2435.     QueryInterface(IID_IHXThinnableSource, (void **)&pThin)))
  2436. {
  2437.     HX_ASSERT(m_ulSubscribedBw > 0);
  2438.     m_ulRateBeforeDeAccel = m_ulLastSetDelivery;
  2439.     UINT32 ulSet;
  2440.     if (m_ulIncomingBandwidth > m_ulMaxSubscribedBw)
  2441.     {
  2442. ulSet = m_ulMaxSubscribedBw;
  2443.     }
  2444.     else
  2445.     {
  2446. ulSet = (UINT32)(m_ulSubscribedBw * 0.75);
  2447.     }
  2448.     DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT, 
  2449. (s, "(%p)Acceleration Buffer Full: NewTransmissionRate=%d %p", m_pSource,
  2450.     ulSet, this));
  2451.     pThin->SetDeliveryBandwidth((m_ulLastSetDelivery = ulSet), 0);
  2452. }
  2453. HX_RELEASE(pThin);
  2454.     }
  2455.     else
  2456. m_pHXASM->RecalcAccel();
  2457.     return HXR_OK;
  2458. }
  2459. INT32
  2460. ASMSourceInfo::CalcBackup(UINT32 ulServerTime, UINT32 ulClientTime)
  2461. {
  2462.     INT32 lNewDiff = ulClientTime - ulServerTime;
  2463.     /* 
  2464.      *  If this is the first time we will have no idea of the base
  2465.      *  time diff.
  2466.      */
  2467.     if(!m_lTimeDiffBase)
  2468.     {
  2469. m_lTimeDiffBase = lNewDiff;
  2470. return 0;
  2471.     }
  2472.     /*
  2473.      * If our difference got shorter than before then this is the new base
  2474.      * and our backup is 0
  2475.      */
  2476.     if(lNewDiff < m_lTimeDiffBase)
  2477.     {
  2478. m_lTimeDiffBase = lNewDiff;
  2479. return 0;
  2480.     }
  2481.     if (m_lLastBehindTime)
  2482.     {
  2483. if (((INT32)m_ulBytesBehind +
  2484.     ((lNewDiff - m_lTimeDiffBase) - m_lLastBehindTime) * 
  2485.     (INT32)m_ulLastSetDelivery / 8000) > 0)
  2486. {
  2487.     m_ulBytesBehind +=
  2488.     ((lNewDiff - m_lTimeDiffBase) - m_lLastBehindTime) * 
  2489.     (INT32)m_ulLastSetDelivery / 8000;
  2490. }
  2491. else
  2492. {
  2493.     m_ulBytesBehind = 0;
  2494. }
  2495.     }
  2496.     m_lLastBehindTime = lNewDiff - m_lTimeDiffBase;
  2497.     DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT_EXTENDED, 
  2498.     (s, "(%p)Terminal Buffer Report: Behind by %dms (%d bytes)", m_pSource,
  2499.     lNewDiff - m_lTimeDiffBase, m_ulBytesBehind));
  2500.     return lNewDiff - m_lTimeDiffBase;
  2501. }
  2502. STDMETHODIMP
  2503. ASMSourceInfo::SetCongestionFactor(UINT32 ulFactor)
  2504. {
  2505.     if (m_bIsDone)
  2506.     {
  2507. return HXR_OK;
  2508.     }
  2509.     return HXR_OK;
  2510. }
  2511. void    
  2512. ASMSourceInfo::ChangeAccelerationStatus(BOOL    bMayBeAccelerated,
  2513. BOOL    bUseAccelerationFactor,
  2514. UINT32    ulAccelerationFactor)
  2515. {
  2516.     if (m_bMayBeAccelerated == FALSE && bMayBeAccelerated == FALSE)
  2517.     {
  2518. DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT, 
  2519. (s, "(%p)Acceleration Buffer Way Full: Factor=%d", m_pSource, ulAccelerationFactor));
  2520. HX_ASSERT(bUseAccelerationFactor);
  2521. UINT32 ulNewRate = m_ulSubscribedBw * ulAccelerationFactor / 100;
  2522. IHXThinnableSource* pThin = NULL;
  2523. if (HXR_OK == m_pSource->
  2524.     QueryInterface(IID_IHXThinnableSource, (void **)&pThin))
  2525. {
  2526.     pThin->SetDeliveryBandwidth((m_ulLastSetDelivery = ulNewRate), 0);
  2527. }
  2528. HX_RELEASE(pThin);
  2529. return;
  2530.     }
  2531.     m_bMayBeAccelerated = bMayBeAccelerated;
  2532.     if (!m_bMayBeAccelerated && (m_ulLastSetDelivery > m_ulSubscribedBw))
  2533.     {
  2534. m_bPendingChill = TRUE;
  2535.     }
  2536.     else if (m_bMayBeAccelerated && m_ulRateBeforeDeAccel)
  2537.     {
  2538. IHXThinnableSource* pThin = NULL;
  2539. if (HXR_OK == m_pSource->
  2540.     QueryInterface(IID_IHXThinnableSource, (void **)&pThin))
  2541. {
  2542.     /* Only attempt conservative restart on LBR sources */
  2543.     if (m_ulRateBeforeDeAccel < 150000)
  2544.     {
  2545. /* Can we be conservative when switching back up? */
  2546. if ((m_ulRateBeforeDeAccel * 0.50) > m_ulSubscribedBw)
  2547. {
  2548.     /* Yes, be really conservative */
  2549.     m_ulRateBeforeDeAccel = (UINT32)
  2550.         (m_ulRateBeforeDeAccel * 0.70);
  2551. }
  2552. else if ((m_ulRateBeforeDeAccel * 0.70) > m_ulSubscribedBw)
  2553. {
  2554.     /* Be somewhat conservative */
  2555.     m_ulRateBeforeDeAccel = (UINT32)
  2556.         (m_ulRateBeforeDeAccel * 0.85);
  2557. }
  2558.     }
  2559.     DEBUG_OUT(m_pHXASM->m_pEM, DOL_TRANSPORT, 
  2560. (s, "(%p)Acceleration Buffer at 50%: NewTransmissionRate=%d", m_pSource, m_ulRateBeforeDeAccel));
  2561.     pThin->SetDeliveryBandwidth(
  2562. (m_ulLastSetDelivery = (UINT32) (m_ulRateBeforeDeAccel)), 0);
  2563.     m_ulRateBeforeDeAccel = 0;
  2564. }
  2565. HX_RELEASE(pThin);
  2566.     }
  2567. }
  2568. STDMETHODIMP
  2569. ASMSourceInfo::SetTransportType(TRANSPORT_TYPE type)
  2570. {
  2571.     if (m_bIsDone)
  2572.     {
  2573. return HXR_OK;
  2574.     }
  2575.     m_TransportType = type;
  2576.     if (m_TransportType == TNG_TCP)
  2577.     {
  2578. THRESHOLD = 5000;
  2579. m_lOuterThreshold = 5000;
  2580.     }
  2581.     return HXR_OK;
  2582. }
  2583. ASMStreamInfo::ASMStreamInfo() :
  2584.     m_pNegotiator(0),
  2585.     m_pBias(0),
  2586.     m_pRuleGather(0),
  2587.     m_ulFixedBandwidth(0),
  2588.     m_ulLastBandwidth(0),
  2589.     m_bTimeStampDelivery(FALSE),
  2590.     m_ulNumThresholds(0),
  2591.     m_ulThresholdPosition(0),
  2592.     m_ulResistanceToLower(0),
  2593.     m_ulOffer(0),
  2594.     m_pThreshold(NULL),
  2595.     m_ulMaxEffectiveThreshold(-1),
  2596.     m_ulStreamNumber(0)
  2597. {
  2598. }
  2599. ASMStreamInfo::~ASMStreamInfo()
  2600. {
  2601.     HX_VECTOR_DELETE(m_pThreshold);
  2602.     HX_RELEASE(m_pNegotiator);
  2603.     HX_RELEASE(m_pBias);
  2604.     HX_RELEASE(m_pRuleGather);
  2605. }