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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: hxsm2.cpp,v 1.9.8.2 2004/07/09 02:05:30 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hxsm2.h"
  50. #include "hxsmutil.h"
  51. #include "ihxpckts.h"
  52. #include "hxprefs.h"
  53. #include "hxpref.h"
  54. #include "hxbsrc.h" /* HXSource */
  55. #include "asmrulep.h" /* ASMRuleBook */
  56. #include "hxbuffer.h" /* CHXBuffer */
  57. #include "chxpckts.h" /* CHXHeader */
  58. #include "safestring.h" /* SafeSprintf */
  59. #include "rtspif.h"     /* RTSPSubscription */
  60. class ASMStreamInfo2;
  61. class ASMSourceInfo2
  62. {
  63. public:
  64.     ASMSourceInfo2(HXSource* pSource);
  65.     ~ASMSourceInfo2();
  66.     UINT32 StreamCount() const;
  67.     ASMStreamInfo2* GetStream(UINT32 i);
  68.     UINT32& SubscribeBw();
  69.     UINT32& LastSetDelivery();
  70.     UINT32& MasterOffer();
  71.     BOOL IsMySource(HXSource* pSource);
  72.     BOOL IsLive();
  73.     BOOL IsPerfectPlay() const;
  74.     BOOL HasMasterRuleBook() const;
  75.     void DistributeBw();
  76.     CHXSimpleList* SubsChanges();
  77.     void SubscribeToChanges();
  78.     void SetDeliveryBw(UINT32 ulMaxBw);
  79.     void Done();
  80. private:
  81.     HX_RESULT GetSubInfo(UINT32 ulBandwidth,
  82.  BOOL* pCurrentSubInfo);
  83.     UINT32 GetStreamBw(IHXValues* pProps, 
  84.        UINT32 ulStreamIndex) const;
  85.     HXSource* m_pSource;
  86.     UINT32 m_ulStreamCount;
  87.     ASMStreamInfo2** m_pStreams;
  88.     UINT32 m_ulSubscribedBw;
  89.     UINT32 m_ulLastSetDelivery;
  90.     UINT32 m_ulMasterOffer;
  91.     BOOL m_bPerfectPlay;
  92.     ASMRuleBook* m_pMasterRuleBook;
  93.     IHXValues* m_pSubsVars;
  94.     CHXSimpleList   m_subsChanges;
  95. };
  96. class ASMStreamInfo2
  97. {
  98. public:
  99.     ASMStreamInfo2(IUnknown* pStream);
  100.     ~ASMStreamInfo2();
  101.     HX_RESULT GetBiasFactor(REF(INT32) lBiasFactor);
  102.     BOOL IsFixedBw() const;
  103.     UINT32 CurrentBw() const;
  104.     UINT32 StreamID() const;
  105.     
  106.     void SetStreamOffer(UINT32 ulOffer);
  107.     void SelectBw(BOOL bPerfectPlay,
  108.   UINT32 ulAltOffer);
  109.     
  110.     UINT32 ResistanceToLower() const;
  111.     void SelectNextLowerBw();
  112.     UINT32 GetLastBw() const;
  113.     void SubscribeToNewBw(UINT32 ulBw, CHXSimpleList* pSubChanges);
  114.     void SubscribeToChanges(CHXSimpleList* pSubChanges);
  115. private:
  116.     void ComputeResistence(BOOL bPerfectPlay);
  117.     BOOL   m_bFixedBwValid;
  118.     UINT32 m_ulFixedBandwidth;
  119.     UINT32 m_ulNumThresholds;
  120.     float* m_pThresholds;
  121.     UINT32 m_ulCurThresh;
  122.     UINT32 m_ulMaxEffectiveThreshold;
  123.     IHXStreamBandwidthBias* m_pBias;
  124.     IHXStreamBandwidthNegotiator* m_pNegotiator;
  125.     IHXAtomicRuleGather* m_pRuleGather;
  126.     UINT32 m_ulStreamID;
  127.     UINT32 m_ulStreamOffer; // From master rulebook
  128.     UINT32 m_ulOffer;       // From SelectBw()
  129.     UINT32 m_ulResistanceToLower;
  130.     UINT32 m_ulLastBw;
  131. };
  132. class ASMStreamInfoItr
  133. {
  134. public:
  135.     ASMStreamInfoItr(CHXSimpleList* pSourceList);
  136.     
  137.     ASMSourceInfo2* Source();
  138.     ASMStreamInfo2* Stream();
  139.     BOOL More() const;
  140.     void Next();
  141.     void Reset();
  142. private:
  143.     void FindNextSource();
  144.     CHXSimpleList* m_pSourceList;
  145.     CHXSimpleList::Iterator m_itr;
  146.     UINT32         m_ulStream;
  147. };
  148. ASMStreamInfoItr::ASMStreamInfoItr(CHXSimpleList* pSourceList) :
  149.     m_pSourceList(pSourceList),
  150.     m_ulStream(0)
  151. {
  152.     Reset();
  153. }
  154. ASMSourceInfo2* ASMStreamInfoItr::Source()
  155. {
  156.     ASMSourceInfo2* pRet = 0;
  157.     
  158.     if (More())
  159.     {
  160. pRet = (ASMSourceInfo2*)(*m_itr);
  161.     }
  162.     return pRet;
  163. }
  164. ASMStreamInfo2* ASMStreamInfoItr::Stream()
  165. {
  166.     ASMStreamInfo2* pRet = 0;
  167.     
  168.     ASMSourceInfo2* pSrc = Source();
  169.     if (pSrc)
  170.     {
  171. pRet = pSrc->GetStream(m_ulStream);
  172.     }
  173.     return pRet;
  174. }
  175. BOOL ASMStreamInfoItr::More() const
  176. {
  177.     return  (m_pSourceList && 
  178.      (m_itr != m_pSourceList->End()));
  179. }
  180. void ASMStreamInfoItr::Next()
  181. {
  182.     if (More())
  183.     {
  184. m_ulStream++;
  185. if (m_ulStream == Source()->StreamCount())
  186. {
  187.     // We are done with this source.
  188.     // Move onto the next one
  189.     m_ulStream = 0;
  190.     ++m_itr;
  191.     FindNextSource();
  192. }
  193.     }
  194. }
  195. void ASMStreamInfoItr::Reset()
  196. {
  197.     if (m_pSourceList)
  198.     {
  199. m_ulStream = 0;
  200. m_itr = m_pSourceList->Begin(); 
  201. FindNextSource();
  202.     }
  203. }
  204. void ASMStreamInfoItr::FindNextSource()
  205. {
  206.     BOOL bDone = FALSE;
  207.     while(!bDone && m_itr != m_pSourceList->End())
  208.     {
  209. ASMSourceInfo2* pSrc = (ASMSourceInfo2*)(*m_itr);
  210. if (pSrc && pSrc->StreamCount() > 0)
  211. {
  212.     bDone = TRUE;
  213. }
  214. else
  215. {
  216.     ++m_itr;
  217. }
  218.     }
  219. }
  220. ASMSourceInfo2::ASMSourceInfo2(HXSource* pSource) :
  221.     m_pSource(pSource),
  222.     m_ulStreamCount(0),
  223.     m_pStreams(0),
  224.     m_ulSubscribedBw(0),
  225.     m_ulLastSetDelivery(0),
  226.     m_ulMasterOffer(0),
  227.     m_bPerfectPlay(FALSE),
  228.     m_pMasterRuleBook(0),
  229.     m_pSubsVars(0)
  230. {
  231.     if (m_pSource)
  232.     {
  233. m_pSource->AddRef();
  234. m_bPerfectPlay = m_pSource->IsPerfectPlay();
  235.         m_ulStreamCount = pSource->GetStreamCount();     
  236. m_pStreams = new ASMStreamInfo2*[m_ulStreamCount];
  237. if (m_pStreams)
  238. {
  239.     for (UINT32 i = 0; i < m_ulStreamCount; i++)
  240.     {
  241. IUnknown* pStream = 0;
  242. HX_VERIFY(HXR_OK == pSource->GetStream(i, pStream));
  243. m_pStreams[i] = new ASMStreamInfo2(pStream);
  244.     
  245. HX_RELEASE(pStream);
  246.     }
  247. }
  248. // Get Master Rulebook
  249. if (pSource->m_pFileHeader)
  250. {
  251.     IHXBuffer* pMasterRuleBook = NULL;
  252.     pSource->m_pFileHeader->
  253. GetPropertyCString("ASMRuleBook", pMasterRuleBook);
  254.     
  255.     if (pMasterRuleBook)
  256.     {
  257. m_pMasterRuleBook = new ASMRuleBook
  258.     ((const char *)pMasterRuleBook->GetBuffer());
  259.     }
  260.     
  261.     HX_RELEASE(pMasterRuleBook);
  262. }
  263.     }
  264. }
  265. ASMSourceInfo2::~ASMSourceInfo2()
  266. {
  267.     if (m_pStreams)
  268.     {
  269. for (UINT32 i = 0; i < m_ulStreamCount; i++)
  270. {
  271.     delete m_pStreams[i];
  272.     m_pStreams[i] = 0;
  273. }
  274. delete [] m_pStreams;
  275.     }
  276.     HX_RELEASE(m_pSource);
  277.     HX_RELEASE(m_pSubsVars);
  278.     delete m_pMasterRuleBook;
  279.     m_pMasterRuleBook = 0;
  280. }
  281. inline
  282. UINT32 ASMSourceInfo2::StreamCount() const
  283. {
  284.     return m_ulStreamCount;
  285. }
  286. ASMStreamInfo2* ASMSourceInfo2::GetStream(UINT32 i)
  287. {
  288.     ASMStreamInfo2* pRet = 0;
  289.     if (m_pStreams && (i < m_ulStreamCount))
  290.     {
  291. pRet = m_pStreams[i];
  292.     }
  293.     return pRet;
  294. }
  295. inline
  296. UINT32& ASMSourceInfo2::SubscribeBw()
  297. {
  298.     return m_ulSubscribedBw;
  299. }
  300. inline
  301. UINT32& ASMSourceInfo2::LastSetDelivery()
  302. {
  303.     return m_ulLastSetDelivery;
  304. }
  305. inline
  306. UINT32& ASMSourceInfo2::MasterOffer()
  307. {
  308.     return m_ulMasterOffer;
  309. }
  310. inline
  311. BOOL ASMSourceInfo2::IsMySource(HXSource* pSource)
  312. {
  313.     return (m_pSource == pSource);
  314. }
  315. BOOL ASMSourceInfo2::IsLive()
  316. {
  317.     BOOL bRet = FALSE;
  318.     if (m_pSource)
  319.     {
  320. bRet = m_pSource->IsLive();
  321.     }
  322.     return bRet;
  323. }
  324. inline
  325. BOOL ASMSourceInfo2::IsPerfectPlay() const
  326. {
  327.     return m_bPerfectPlay;
  328. }
  329. inline
  330. BOOL ASMSourceInfo2::HasMasterRuleBook() const
  331. {
  332.     return (m_pMasterRuleBook != NULL);
  333. }
  334. void ASMSourceInfo2::DistributeBw()
  335. {
  336.     if (m_pMasterRuleBook)
  337.     {
  338. UINT32 ulRuleCount = m_pMasterRuleBook->GetNumRules();
  339. BOOL* pCurrentSubInfo = new BOOL[ulRuleCount];
  340. GetSubInfo(m_ulMasterOffer, pCurrentSubInfo);
  341. for (UINT16 idxRule = 0; idxRule < ulRuleCount; idxRule++)
  342. {
  343.     if (pCurrentSubInfo[idxRule])
  344.     {
  345. IHXValues* pProps = 0;
  346. // Set Distribution
  347. m_pMasterRuleBook->GetProperties(idxRule, pProps);
  348. for (UINT32 j = 0; j < m_ulStreamCount; j++)
  349. {
  350.     UINT32 ulStreamBw = GetStreamBw(pProps, j);
  351.     m_pStreams[j]->SetStreamOffer(ulStreamBw);
  352. }
  353. HX_RELEASE(pProps);
  354. break;
  355.     }
  356. }
  357. delete [] pCurrentSubInfo;
  358.     }
  359. }
  360. inline
  361. CHXSimpleList* ASMSourceInfo2::SubsChanges()
  362. {
  363.     return &m_subsChanges;
  364. }
  365. void ASMSourceInfo2::SubscribeToChanges()
  366. {
  367.     if (!m_subsChanges.IsEmpty() && m_pStreams && m_pStreams[0])
  368.     {
  369. m_pStreams[0]->SubscribeToChanges(&m_subsChanges);
  370. while(!m_subsChanges.IsEmpty())
  371. {
  372.     RTSPSubscription* pSub = (RTSPSubscription*)m_subsChanges.RemoveHead();
  373.     delete pSub;
  374. }
  375.     }
  376. }
  377. void ASMSourceInfo2::SetDeliveryBw(UINT32 ulMaxBw)
  378. {
  379.     if (m_pStreams)
  380.     {
  381. UINT32 ulTotalBw = 0;
  382. // Calculate the total BW used by the streams
  383. for (UINT32 i = 0; i < m_ulStreamCount; i++)
  384. {
  385.     ulTotalBw += m_pStreams[i]->CurrentBw();
  386. }
  387. m_ulSubscribedBw = ulTotalBw;
  388. if (ulTotalBw)
  389. {
  390.     IHXThinnableSource* pThin = 0;
  391.     
  392.     if (HXR_OK == m_pSource->QueryInterface(IID_IHXThinnableSource, 
  393.     (void **)&pThin))
  394.     {
  395. /* Clamp bandwidth request */
  396. if (ulTotalBw > ulMaxBw)
  397. {
  398.     ulTotalBw = ulMaxBw;
  399. }
  400. pThin->SetDeliveryBandwidth(ulTotalBw, 0);
  401. HX_RELEASE(pThin);
  402.     }
  403. }
  404.     }
  405. }
  406. inline
  407. void ASMSourceInfo2::Done()
  408. {
  409.     HX_RELEASE(m_pSource);
  410. }
  411. HX_RESULT ASMSourceInfo2::GetSubInfo(UINT32 ulBandwidth,
  412.      BOOL* pCurrentSubInfo)
  413. {
  414.     HX_RESULT res = HXR_FAILED;
  415.     if (m_pMasterRuleBook)
  416.     {
  417. res = HXSMUpdateSubscriptionVars(m_pSubsVars, ulBandwidth, FALSE, 0);
  418. if (HXR_OK == res)
  419. {
  420.     res = m_pMasterRuleBook->GetSubscription(pCurrentSubInfo, 
  421.      m_pSubsVars);
  422. }
  423.     }
  424.     return res;
  425. }
  426. UINT32 ASMSourceInfo2::GetStreamBw(IHXValues* pProps, 
  427.    UINT32 ulStreamIndex) const
  428. {
  429.     UINT32 ulRet = 0;
  430.     UINT8       pTemp[128];
  431.     IHXBuffer* pBw = NULL;
  432.     HX_RESULT   hxResult;
  433.     
  434.     // Don't assume that streamid == index in m_pStreams[j]
  435.     sprintf((char *)pTemp, 
  436.     "Stream%ldBandwidth", 
  437.     m_pStreams[ulStreamIndex]->StreamID()); /* Flawfinder: ignore */
  438.     
  439.     /*
  440.      * if this tripps either there's a bug in here or
  441.      * the content is messed up
  442.      *
  443.      */
  444.     //If the Stream?Bandwidth property isn't found for
  445.     //all streams don't worry about it. Not all streams
  446.     //may have rule books.
  447.     hxResult = pProps->GetPropertyCString((char *)pTemp, pBw);
  448.     if(HXR_OK == hxResult && pBw)
  449.     {
  450. ulRet = atoi((char*)pBw->GetBuffer());
  451. HX_RELEASE(pBw);
  452.     }
  453.     return ulRet;
  454. }
  455. ASMStreamInfo2::ASMStreamInfo2(IUnknown* pStream) :
  456.     m_bFixedBwValid(FALSE),
  457.     m_ulFixedBandwidth(0),
  458.     m_ulNumThresholds(0),
  459.     m_pThresholds(0),
  460.     m_ulCurThresh(0),
  461.     m_ulMaxEffectiveThreshold(0),
  462.     m_pBias(0),
  463.     m_pNegotiator(0),
  464.     m_pRuleGather(0),
  465.     m_ulStreamID(0),
  466.     m_ulStreamOffer(0),
  467.     m_ulOffer(0),
  468.     m_ulResistanceToLower(0xffffffff)
  469. {
  470.     if (pStream)
  471.     {
  472. if (HXR_OK == pStream->QueryInterface
  473.     (IID_IHXStreamBandwidthNegotiator,
  474.      (void **)&m_pNegotiator))
  475. {
  476.     m_pNegotiator->GetFixedBandwidth(m_ulFixedBandwidth);
  477.     if (m_ulFixedBandwidth)
  478.     {
  479. /* We need to check to see if the fixed bandwidth value
  480.  * matches the ASMProps Bandwidth value. If it doesn't then
  481.  * that means that we are dealing with a clip that doesn't
  482.  * advertise any bandwidth information. This is a corner
  483.  * case discover by streaming some unhinted .3gp files.
  484.  */
  485. IHXASMProps* pASMProps = NULL;
  486. UINT32 ulASMBw = 0;
  487. if ((HXR_OK == pStream->QueryInterface(IID_IHXASMProps,
  488.        (void**)&pASMProps))&&
  489.     (HXR_OK == pASMProps->GetBandwidth(ulASMBw)) &&
  490.     (m_ulFixedBandwidth == ulASMBw))
  491. {
  492.     m_bFixedBwValid = TRUE;
  493. }
  494. HX_RELEASE(pASMProps);
  495.     }
  496.     else
  497.     {
  498. m_ulNumThresholds = m_pNegotiator->GetNumThresholds();
  499. m_pThresholds = new float[m_ulNumThresholds];
  500. if (m_pThresholds)
  501. {
  502.     m_pNegotiator->GetThresholdInfo(m_pThresholds, 
  503. m_ulNumThresholds);
  504.     m_ulMaxEffectiveThreshold = m_ulNumThresholds - 1;
  505. }
  506.     }
  507. }
  508. pStream->QueryInterface(IID_IHXStreamBandwidthBias,
  509. (void **)&m_pBias);
  510. pStream->QueryInterface(IID_IHXAtomicRuleGather,
  511. (void **)&m_pRuleGather);
  512. // Get StreamID
  513. IHXStream* pHXStream = 0;
  514. pStream->QueryInterface(IID_IHXStream, (void**)&pHXStream);
  515. if (pHXStream)
  516.         {
  517.             m_ulStreamID = pHXStream->GetStreamNumber();
  518.             pHXStream->Release();
  519.         }
  520.     }
  521. }
  522. ASMStreamInfo2::~ASMStreamInfo2()
  523. {
  524.     delete [] m_pThresholds;
  525.     m_pThresholds = 0;
  526.     HX_RELEASE(m_pBias);
  527.     HX_RELEASE(m_pNegotiator);
  528.     HX_RELEASE(m_pRuleGather);
  529. }
  530. HX_RESULT ASMStreamInfo2::GetBiasFactor(REF(INT32) lBiasFactor)
  531. {
  532.     HX_RESULT res = HXR_FAILED;
  533.     
  534.     if (m_pBias)
  535.     {
  536. res = m_pBias->GetBiasFactor(lBiasFactor);
  537.     }
  538.     return res;
  539. }
  540. inline
  541. BOOL ASMStreamInfo2::IsFixedBw() const
  542. {
  543.     return (m_ulFixedBandwidth != 0);
  544. }
  545. UINT32 ASMStreamInfo2::CurrentBw() const
  546. {
  547.     UINT32 ulRet = (m_bFixedBwValid) ? m_ulFixedBandwidth : 0;
  548.     if (!ulRet && m_pThresholds)
  549.     {
  550. ulRet = (UINT32)m_pThresholds[m_ulCurThresh];
  551.     }
  552.     return ulRet;
  553. }
  554. inline
  555. UINT32 ASMStreamInfo2::StreamID() const
  556. {
  557.     return m_ulStreamID;
  558. }
  559. inline
  560. void ASMStreamInfo2::SetStreamOffer(UINT32 ulOffer)
  561. {
  562.     m_ulStreamOffer = ulOffer;
  563. }
  564. void ASMStreamInfo2::SelectBw(BOOL bPerfectPlay,
  565.       UINT32 ulAltOffer)
  566. {
  567.     if (m_pThresholds)
  568.     {
  569. if (bPerfectPlay)
  570. {
  571.     /*
  572.      * If we are in perfect play mode, just select the highest bandwidth rule
  573.      * and don't negotiate any further.
  574.      */
  575.     m_ulCurThresh = m_ulMaxEffectiveThreshold;
  576.     m_ulOffer = CurrentBw();
  577. }
  578. else
  579.     UINT32 ulOffer = ulAltOffer;
  580.     if (m_ulStreamOffer)
  581.     {
  582. ulOffer = m_ulStreamOffer - 1;
  583.     }
  584.     
  585.     if (m_ulMaxEffectiveThreshold != 0)
  586.     {
  587. for (UINT32 i = 1; i <= m_ulMaxEffectiveThreshold; i++)
  588. {
  589.     if ((ulOffer <= m_pThresholds[i]) ||
  590. (i == m_ulMaxEffectiveThreshold))
  591.     {
  592. m_ulOffer = ulOffer;
  593. m_ulCurThresh = i;
  594. break;
  595.     }
  596. }
  597.     }
  598. }
  599. ComputeResistence(bPerfectPlay);
  600.     }
  601. }
  602. inline
  603. UINT32 ASMStreamInfo2::ResistanceToLower() const
  604. {
  605.     return m_ulResistanceToLower;
  606. }
  607. void ASMStreamInfo2::SelectNextLowerBw()
  608. {
  609.     if (m_ulCurThresh > 0)
  610.     {
  611. m_ulCurThresh--;
  612. ComputeResistence(FALSE);
  613.     }
  614. }
  615. inline
  616. UINT32 ASMStreamInfo2::GetLastBw() const
  617. {
  618.     return m_ulLastBw;
  619. }
  620. void ASMStreamInfo2::SubscribeToNewBw(UINT32 ulBw, CHXSimpleList* pSubChanges)
  621. {
  622.     BOOL bTimeStampDelivery = FALSE;
  623.     
  624.     if (m_pRuleGather && m_pNegotiator)
  625.     {
  626. m_pRuleGather->RuleGather(pSubChanges);
  627. //update the HXASMStream with our new bandwidth
  628. m_pNegotiator->SetBandwidthUsage(ulBw, bTimeStampDelivery);
  629. m_pRuleGather->RuleGather(0);
  630.     }
  631.     m_ulLastBw = ulBw;
  632. }
  633. void ASMStreamInfo2::SubscribeToChanges(CHXSimpleList* pSubChanges)
  634. {
  635.     if (m_pRuleGather)
  636.     {
  637. m_pRuleGather->RuleFlush(pSubChanges);
  638.     }
  639. }
  640. void ASMStreamInfo2::ComputeResistence(BOOL bPerfectPlay)
  641. {
  642.     /* NOTE:
  643.      * m_ulCurThresh and m_ulOffer must
  644.      * be valid when this function is called
  645.      */
  646.     if (IsFixedBw() || 
  647. bPerfectPlay ||
  648. (m_ulMaxEffectiveThreshold == 0) ||
  649. (m_ulCurThresh == 1))
  650.     {
  651. m_ulResistanceToLower = 0xffffffff;
  652.     }
  653.     else
  654.     {
  655. m_ulResistanceToLower = 
  656.     (m_ulOffer - (UINT32)m_pThresholds[m_ulCurThresh - 1]) * m_ulOffer;
  657.     }
  658. }
  659. HXSM2::HXSM2() :
  660.     m_lRefCount(0),
  661.     m_ulNumSources(0),
  662.     m_pASMSourceInfo(0),
  663.     m_ulNumStreams(0),
  664.     m_ulOfferToRecalc(0),
  665.     m_ulSelectionBitRate(0),
  666.     m_ulMaxAccelBitRate(0),
  667.     m_ulSustainableBitRate(0),
  668.     m_pSubscriptionVariables(0),
  669.     m_bCheckOnDemandBw(FALSE)
  670. {
  671.     m_pASMSourceInfo = new CHXSimpleList();
  672. }
  673. HXSM2::~HXSM2()
  674. {
  675.     if (m_pASMSourceInfo)
  676.     {
  677. while(!m_pASMSourceInfo->IsEmpty())
  678. {
  679.     ASMSourceInfo2* pSrc = 
  680. (ASMSourceInfo2*)m_pASMSourceInfo->RemoveHead();
  681.     delete pSrc;
  682. }
  683. delete m_pASMSourceInfo;
  684.     }
  685. }
  686. STDMETHODIMP HXSM2::QueryInterface(THIS_ REFIID ID, void** ppInterfaceObj)
  687. {
  688. QInterfaceList qiList[] =
  689. {
  690. { GET_IIDHANDLE(IID_IUnknown), this },
  691. { GET_IIDHANDLE(IID_IHXBandwidthManager), (IHXBandwidthManager*) this },
  692. };
  693.     return QIFind(qiList, QILISTSIZE(qiList), ID, ppInterfaceObj);
  694. }
  695. STDMETHODIMP_(UINT32) HXSM2::AddRef(THIS)
  696. {
  697.     return InterlockedIncrement(&m_lRefCount);
  698. }
  699. STDMETHODIMP_(UINT32) HXSM2::Release(THIS)
  700. {
  701.     if (InterlockedDecrement(&m_lRefCount) > 0)
  702.     {
  703. return m_lRefCount;
  704.     }
  705.     delete this;
  706.     return 0;
  707. }
  708. /*
  709.  * IHXBandwidthManager methods
  710.  */
  711. STDMETHODIMP HXSM2::RegisterSource(THIS_
  712.    HXSource* pSource,
  713.    IUnknown* pUnknown)
  714. {
  715.     HX_RESULT res = HXR_OK;
  716.     IHXSourceBandwidthInfo* pSBI;
  717.     IHXPreferences* pPreferences = NULL;
  718.     IHXBuffer* pBuffer = 0;
  719.     ASMSourceInfo2* pASMSourceInfo = NULL;
  720.     if (HXR_OK == pSource->QueryInterface(IID_IHXSourceBandwidthInfo, 
  721.             (void **)&pSBI))
  722.     {
  723.         pASMSourceInfo = new ASMSourceInfo2(pSource);
  724.         m_ulNumSources++;
  725.         m_ulNumStreams += pASMSourceInfo->StreamCount();
  726.         m_pASMSourceInfo->AddTail((void *)pASMSourceInfo);
  727.         HX_RELEASE(pSBI);
  728.     }
  729.     else
  730.     {
  731.         return HXR_OK;
  732.     }
  733.     /*
  734.      * This variable tells us the highest amount of bandwidth that we
  735.      * believe is useable.  If we stream thin, then the highest value
  736.      * that the pipe can support would be the aggregate bandwidth of
  737.      * the sources.  Barring any thinning, this would be the bandwidth
  738.      * from prefs (unless we can determine it through fast buffering or
  739.      * another transport feature).  This value is used when starting sources
  740.      * as a initial guess for bandwidth (to set subscriptions).
  741.      */
  742.     if (m_ulSelectionBitRate == 0)
  743.     {
  744.         pUnknown->QueryInterface(IID_IHXPreferences, (void **)&pPreferences);
  745.         UINT32 ulTemp = 0;
  746.         UINT32 ulConnectionBw = 10485760; /* wild guess */
  747.         /* Get initial bandwidth guess from Prefs */
  748.         if ((HXR_OK == ReadPrefINT32(pPreferences, "Bandwidth", ulTemp)) &&
  749.             (ulTemp > 0))
  750.         {
  751.             ulConnectionBw = ulTemp;
  752.         }
  753.         /*
  754.          * m_ulSustainableBitRate refers to the max bitrate that we believe is
  755.          * sustainable over the connection. The client should never ask
  756.          * the server to send bits faster than this rate because it could
  757.          * cause congestion collapse.
  758.          *
  759.          * m_ulSelectionBitRate refers to the highest bitrate stream that we'll
  760.          * ever try to play. Note that people can choose to pick values
  761.          * where m_ulSelectionBitRate > m_ulSustainableBitRate. This may
  762.  * cause rebuffers because the delivery will be capped at 
  763.  * m_ulSustainableBitRate. Why would someone do that? They may accept
  764.  * rebuffers if it means they get a higher quality presentation.
  765.          */
  766.         
  767.         /* See if we have a sustainable bandwidth factor */
  768.         if (HXR_OK == ReadPrefINT32(pPreferences, "SustainableBwFactor", 
  769.                                     ulTemp))
  770.         {
  771.             /* clamp value to 0 <= ulTemp <= 100 range */
  772.             if (ulTemp > 100)
  773.             {
  774.                 ulTemp = 100;
  775.             }
  776.             
  777.             /* Apply factor */
  778.             m_ulSustainableBitRate = 
  779.                 (((ulConnectionBw / 100) * ulTemp) + 
  780.                  (((ulConnectionBw % 100) * ulTemp) / 100));
  781.         }
  782.         else
  783.         {
  784.             m_ulSustainableBitRate = ulConnectionBw;
  785.         }
  786.         
  787.         /* See if we have a selection bandwidth factor */
  788.         if (HXR_OK == ReadPrefINT32(pPreferences, "SelectionBwFactor", 
  789.                                     ulTemp))
  790.         {
  791.             /* clamp value to 0 <= ulTemp <= 200 range */
  792.             if (ulTemp > 200)
  793.             {
  794.                 ulTemp = 200;
  795.             }
  796.             
  797.             /* Apply factor */
  798.             m_ulSelectionBitRate  = 
  799.                 (((m_ulSustainableBitRate / 100) * ulTemp) + 
  800.                  (((m_ulSustainableBitRate % 100) * ulTemp) / 100));
  801.         }
  802.         else
  803.         {
  804.             m_ulSelectionBitRate = m_ulSustainableBitRate; 
  805.         }
  806.         /* Get MaxBandwidth from Prefs */
  807.         if (HXR_OK != ReadPrefINT32(pPreferences, "MaxBandwidth", 
  808.                                     m_ulMaxAccelBitRate))
  809.         {
  810.             /* 
  811.              * Failed to get the MaxBandwidth preference. 
  812.              * Use m_ulSelectionBitRate value instead.
  813.              */
  814.             m_ulMaxAccelBitRate = m_ulSelectionBitRate;
  815.         }
  816.         /* 
  817.          * Get preference that controls whether we report
  818.          * "not enough bandwidth" conditions for on-demand clips
  819.          */
  820.         ReadPrefBOOL(pPreferences, "CheckOnDemandBw", m_bCheckOnDemandBw);
  821.         HX_RELEASE(pPreferences);
  822.     }
  823.     return res;
  824. }
  825. STDMETHODIMP HXSM2::RegisterSourcesDone(THIS)
  826. {
  827.     CHXSimpleList::Iterator     i;
  828.     ASMSourceInfo2*    pASMSourceInfo;
  829.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  830.     {
  831. pASMSourceInfo = (ASMSourceInfo2*)(*i);
  832. if (pASMSourceInfo)
  833. {
  834.     pASMSourceInfo->LastSetDelivery() = 0;
  835. }
  836.     }
  837.     
  838.     m_ulOfferToRecalc = m_ulSelectionBitRate;
  839.     if (m_ulOfferToRecalc > m_ulMaxAccelBitRate)
  840.     {
  841. m_ulOfferToRecalc = m_ulMaxAccelBitRate;
  842.     }
  843.     Recalc();
  844.     return HXR_OK;
  845. }
  846.     
  847. STDMETHODIMP_(BOOL) HXSM2::NotEnoughBandwidth(THIS)
  848. {
  849.     CHXSimpleList::Iterator i;
  850.     ASMSourceInfo2*          pASMSourceInfo;
  851.     UINT32     ulTotal = 0;
  852.     BOOL     bCheckTotal = m_bCheckOnDemandBw;
  853.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  854.     {
  855. pASMSourceInfo = (ASMSourceInfo2*)(*i);
  856. ulTotal += pASMSourceInfo->SubscribeBw();
  857. if (pASMSourceInfo->IsLive())
  858. {
  859.     bCheckTotal = TRUE;
  860. }
  861.     }
  862.     if (bCheckTotal && ulTotal > m_ulSelectionBitRate)
  863.     {
  864. return TRUE;
  865.     }
  866.     else
  867.     {
  868. return FALSE;
  869.     }
  870. }
  871. STDMETHODIMP HXSM2::UnRegisterSource(THIS_
  872.      HXSource* pSource)
  873. {
  874.     LISTPOSITION lPos;
  875.     ASMSourceInfo2*             pASMSourceInfo = 0;
  876.     BOOL bFound = FALSE;
  877.     lPos = m_pASMSourceInfo->GetHeadPosition();
  878.     while (lPos)
  879.     {
  880. pASMSourceInfo = (ASMSourceInfo2*)m_pASMSourceInfo->GetAt(lPos);
  881. if (pASMSourceInfo->IsMySource(pSource))
  882. {
  883.     m_pASMSourceInfo->RemoveAt(lPos);
  884.     pASMSourceInfo->Done();
  885.     bFound  = TRUE;
  886.     break;
  887. }
  888. m_pASMSourceInfo->GetNext(lPos);
  889.     }
  890.     
  891.     if (bFound)
  892.     {
  893. m_ulNumStreams -= pASMSourceInfo->StreamCount();
  894. delete pASMSourceInfo;
  895. m_ulNumSources--;
  896. if (m_ulNumSources > 0)
  897. {
  898.     Recalc();
  899. }
  900.     }
  901.     return HXR_OK;
  902. }
  903. STDMETHODIMP HXSM2::ChangeAccelerationStatus(THIS_
  904. HXSource* pSource,
  905. BOOL    bMayBeAccelerated,
  906. BOOL    bUseAccelerationFactor,
  907. UINT32    ulAccelerationFactor)
  908. {
  909.     return HXR_OK;
  910. }
  911.     /* Called by HXPlayer at end of each presentation */
  912. STDMETHODIMP HXSM2::PresentationDone(THIS)
  913. {
  914.     return HXR_OK;
  915. }
  916.     
  917. STDMETHODIMP HXSM2::ChangeBW(THIS_ 
  918.      UINT32 newBW, HXSource* pSource)
  919. {
  920.     return HXR_OK;
  921. }
  922. void
  923. HXSM2::Recalc()
  924. {
  925.     CHXSimpleList::Iterator     i;
  926.     ASMStreamInfoItr            streamItr(m_pASMSourceInfo);
  927.     ASMSourceInfo2*             pASMSourceInfo;
  928.     ASMStreamInfo2*             pASMStreamInfo;
  929.     INT32 lAggregateBandwidthUsage = 0;
  930.     UINT32 ulSourceCount;
  931.     UINT32 ulStreamCount;
  932.     float fBiasMean = (float) 0.;
  933.     ulSourceCount = m_pASMSourceInfo->GetCount();
  934.     ulStreamCount = m_ulNumStreams;
  935.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  936.     {
  937. pASMSourceInfo = (ASMSourceInfo2*)(*i);
  938.         /* Init these for later */
  939. pASMSourceInfo->MasterOffer() = 0;
  940.     }
  941.     lAggregateBandwidthUsage = m_ulOfferToRecalc;
  942.     INT32 lCorrectAggregateBandwidthUsage = lAggregateBandwidthUsage;
  943.     /*
  944.      * For each stream that is at a fixed bitrate, remove that bitrate
  945.      * from our available bandwidth.
  946.      */
  947.     for (streamItr.Reset(); streamItr.More(); streamItr.Next())
  948.     {
  949.         INT32 lBias;
  950. pASMStreamInfo = streamItr.Stream();
  951. HX_VERIFY(HXR_OK == pASMStreamInfo->GetBiasFactor(lBias));
  952. fBiasMean += lBias;
  953. if (pASMStreamInfo->IsFixedBw())
  954. {
  955.     lAggregateBandwidthUsage -= pASMStreamInfo->CurrentBw();
  956.     ulStreamCount--;
  957. }
  958. /* Init this for later */
  959. pASMStreamInfo->SetStreamOffer(0);
  960.     }
  961.     if (ulStreamCount != 0)
  962.     {
  963.         /* At least 1 stream is not fixed bandwidth */
  964.         fBiasMean /= ulStreamCount;
  965.         
  966.         /*
  967.          * Calculate the offer for each source that has a master rulebook
  968.          * defining it's bandwidth division.
  969.          */
  970.         INT32 lNewAggregateBandwidthUsage = lAggregateBandwidthUsage;
  971.         for (streamItr.Reset(); streamItr.More(); streamItr.Next())
  972.         {
  973.             INT32 lBias;
  974.             
  975.             pASMStreamInfo = streamItr.Stream();
  976.             pASMSourceInfo = streamItr.Source();
  977.             
  978.             HX_VERIFY(HXR_OK == pASMStreamInfo->GetBiasFactor(lBias));
  979.             
  980.             if (pASMSourceInfo->HasMasterRuleBook())
  981.             {
  982.                 UINT32 ulOffer = 
  983.                     (UINT32)(lAggregateBandwidthUsage / ulStreamCount);
  984.                 
  985.                 ulOffer += 
  986.                     (UINT32)(((float)lBias - fBiasMean) *
  987.                              ((float)lAggregateBandwidthUsage / 100.0) *
  988.                              (2.0 / ulStreamCount));
  989.                 
  990.                 pASMSourceInfo->MasterOffer() += ulOffer;
  991.                 lNewAggregateBandwidthUsage -= ulOffer;
  992.             }
  993.         }
  994.         lAggregateBandwidthUsage = lNewAggregateBandwidthUsage;
  995.     }
  996.     /*
  997.      * For each source that has a master rule book, evaluate it to find
  998.      * out how much to distribute to each stream.
  999.      */
  1000.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  1001.     {
  1002. pASMSourceInfo = (ASMSourceInfo2*)(*i);
  1003. if (pASMSourceInfo->HasMasterRuleBook())
  1004. {
  1005.     pASMSourceInfo->DistributeBw();
  1006. }
  1007.     }
  1008.     /*
  1009.      *  Now go through each of the streams that are not at a
  1010.      *  fixed bitrate and try to distribute the rest of the bandwidth.
  1011.      */
  1012.     UINT32 ulTakenBandwidth = 0;
  1013.     for (streamItr.Reset(); streamItr.More(); streamItr.Next())
  1014.     {
  1015. pASMStreamInfo = streamItr.Stream();
  1016. if (!pASMStreamInfo->IsFixedBw())
  1017. {
  1018.     INT32 lBias;
  1019.     
  1020.     HX_VERIFY(HXR_OK == pASMStreamInfo->GetBiasFactor(lBias));
  1021.     
  1022.     UINT32 ulAltOffer =
  1023. (UINT32)(lAggregateBandwidthUsage / (float)ulStreamCount);
  1024.     ulAltOffer += (UINT32)(((float)lBias - fBiasMean) *
  1025.    ((float)lAggregateBandwidthUsage / 100.0) *
  1026.    (2.0 / (float)ulStreamCount));
  1027.     pASMStreamInfo->SelectBw(streamItr.Source()->IsPerfectPlay(),
  1028.      ulAltOffer);
  1029. }
  1030. ulTakenBandwidth += pASMStreamInfo->CurrentBw();
  1031.     }
  1032.     lAggregateBandwidthUsage = lCorrectAggregateBandwidthUsage;
  1033.     BOOL bDone = FALSE;
  1034.     while (!bDone && (lAggregateBandwidthUsage < (INT32)ulTakenBandwidth))
  1035.     {
  1036. /* Resistance is Futile.  You will be Real(tm)lyAssimilated */
  1037. UINT32 ulLowestResistance = 0xffffffff;
  1038. ASMStreamInfo2* pLowestResistanceStream  = 0;
  1039. // Find the stream with the lowest resistence
  1040. for (streamItr.Reset(); streamItr.More(); streamItr.Next())
  1041. {
  1042.     pASMStreamInfo = streamItr.Stream();
  1043.     if (pASMStreamInfo->ResistanceToLower() < ulLowestResistance)
  1044.     {
  1045. ulLowestResistance = pASMStreamInfo->ResistanceToLower();
  1046. pLowestResistanceStream = pASMStreamInfo;
  1047.     }
  1048. }
  1049. if (ulLowestResistance == 0xffffffff)
  1050. {
  1051.     bDone = TRUE;
  1052. }
  1053. else
  1054. {
  1055.     ulTakenBandwidth -= (UINT32)
  1056. pLowestResistanceStream->CurrentBw();
  1057.     pLowestResistanceStream->SelectNextLowerBw();
  1058.     ulTakenBandwidth += (UINT32)
  1059. pLowestResistanceStream->CurrentBw();
  1060. }
  1061.     }
  1062.     UINT32 ulLeftOverForDropByN = lAggregateBandwidthUsage - ulTakenBandwidth;
  1063.     BOOL bForce = FALSE;
  1064.     for (streamItr.Reset(); streamItr.More(); streamItr.Next())
  1065.     {
  1066. pASMStreamInfo = streamItr.Stream();
  1067. UINT32 ulBw = pASMStreamInfo->CurrentBw();
  1068. if (ulBw == 1)
  1069. {
  1070.     // Hack Alert for DropByN. XXXSMP
  1071.     ulBw = ulLeftOverForDropByN;
  1072. }
  1073. if ((ulBw != pASMStreamInfo->GetLastBw()) &&
  1074.     (pASMStreamInfo->IsFixedBw()))
  1075. {
  1076.     bForce = TRUE;
  1077. }
  1078. CHXSimpleList* pSubsChanges = 
  1079.     streamItr.Source()->SubsChanges();
  1080. pASMStreamInfo->SubscribeToNewBw(ulBw, pSubsChanges);
  1081.     }
  1082.     for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
  1083.     {
  1084. pASMSourceInfo = (ASMSourceInfo2*)(*i);
  1085. pASMSourceInfo->SubscribeToChanges();
  1086. pASMSourceInfo->SetDeliveryBw(m_ulSustainableBitRate);
  1087.     }
  1088. }