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

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