hxsm.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:83k
源码类别:

Symbian

开发平台:

C/C++

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