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

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 "hlxclib/stdio.h"      /* printf */
  36. #include "hlxclib/stdlib.h"     /* atoi on Mac */
  37. #include "hxtypes.h"    /* Basic Types */
  38. #include "hxcom.h"      /* IUnknown */ 
  39. #include "hxcore.h"    /* IHXStream */
  40. #include "hxerror.h"
  41. #include "hxasm.h"
  42. #include "hxsmbw.h"
  43. #include "hxmap.h"
  44. #include "hxcomm.h"
  45. #include "hxengin.h"
  46. #include "hxsmstr.h" /* HXASMStream */
  47. #include "hxsmutil.h"
  48. #include "ihxpckts.h"
  49. #include "hxprefs.h"
  50. #include "hxstrm.h"
  51. #include "hxcore.h"
  52. #include "asmrulep.h"
  53. #include "hxmon.h"
  54. #include "chxpckts.h"
  55. #include "hxassert.h"
  56. #include "hxslist.h"
  57. #include "hxbsrc.h"
  58. #include "hxsrc.h"
  59. #include "hxstrutl.h"
  60. #include "errdbg.h"
  61. #include "rtspif.h"
  62. #include "rlstate.h"
  63. #include "hxmime.h"
  64. #include "hxheap.h"
  65. #ifdef _DEBUG
  66. #undef HX_THIS_FILE
  67. static const char HX_THIS_FILE[] = __FILE__;
  68. #endif
  69. HXASMStream::HXASMStream(HXStream* pStream, HXSource* pSource)
  70.     : m_lRefCount(0)
  71.     , m_pRuleBook(0)
  72.     , m_pLossCB(0)
  73.     , m_ulLossCBHandle(0)
  74.     , m_pSubInfo(0)
  75.     , m_ulRuleBw(0)
  76.     , m_ulRulePreData(0)
  77.     , m_ulCurrentPreData(0)
  78.     , m_ulCurrentBandwidth(0)
  79.     , m_bRuleTimeStampDelivery(0)
  80.     , m_ulSubscribedBw(0)
  81.     , m_lBias(0)
  82.     , m_ulFixedBandwidth(0)
  83.     , m_ulBandwidthAllocation(0)
  84.     , m_bStartRecalc(FALSE)
  85.     , m_bTimeStampDeliveryMode(FALSE)
  86.     , m_ulLastLimitBandwidth(0xffffffff)
  87.     , m_pAtomicRuleChange(0)
  88.     , m_pSubList(0)
  89.     , m_pSubscriptionVariables(0)
  90.     , m_nNumRules(0)    
  91.     , m_pRuleSubscribeStatus(NULL)
  92.     , m_pASMRuleState(NULL)
  93.     , m_bHasExpression(FALSE)
  94.     , m_bEndOneRuleEndAll(FALSE)
  95.     , m_ulLastBandwidth(0)
  96. #ifndef GOLD
  97.     , m_pEM(0)
  98. #endif
  99. {
  100.     m_pStreamSinkMap = new CHXMapPtrToPtr;
  101.     
  102.     UINT32  ulStreamID;
  103.     IHXPlayer* pPlayer;
  104.     IHXPreferences* pPreferences=NULL;    
  105.     pStream->GetID(ulStreamID);
  106.     m_pSource = pSource;
  107.     m_pSource->AddRef();
  108.     m_pHeader = pStream->GetHeader();
  109.     m_uStreamNumber = pStream->GetStreamNumber();
  110.     /* Hold onto some useful interfaces */
  111.     m_pSource->GetPlayer(pPlayer);
  112.     pPlayer->QueryInterface(IID_IHXRegistry,  (void **)&m_pRegistry);
  113.     pPlayer->QueryInterface(IID_IHXScheduler,   (void **)&m_pScheduler);
  114.     pPlayer->Release();
  115.     /*
  116.      * WARNING!  You must update all interfaces queried off the source
  117.      * in ResetASMSource().
  118.      */
  119.     m_pSource->QueryInterface(IID_IHXASMSource, (void **)&m_pASMSource);
  120.     m_pSource->QueryInterface(IID_IHXAtomicRuleChange,
  121. (void **)&m_pAtomicRuleChange);
  122. #ifndef GOLD
  123.     pPlayer->QueryInterface(IID_IHXErrorMessages, (void **)&m_pEM);
  124. #endif
  125.     UINT32 ulEndOneruleEndAll = 0;
  126.     if (m_pHeader->GetPropertyULONG32("EndOneRuleEndAll", ulEndOneruleEndAll) == HXR_OK)
  127.     {
  128. m_bEndOneRuleEndAll = (ulEndOneruleEndAll == 1);
  129.     }
  130.     /* temporary hack to properly shut down RA and RV streams with end time */
  131.     else
  132.     {
  133. IHXBuffer* pMimeType = NULL;
  134. m_pHeader->GetPropertyCString("MimeType", pMimeType);
  135. if (pMimeType && 
  136.     ((::strcasecmp((const char*) pMimeType->GetBuffer(), REALAUDIO_MIME_TYPE) == 0) ||
  137.      (::strcasecmp((const char*) pMimeType->GetBuffer(), REALAUDIO_MULTIRATE_MIME_TYPE) == 0) ||
  138.      (::strcasecmp((const char*) pMimeType->GetBuffer(), REALVIDEO_MIME_TYPE) == 0) ||
  139.      (::strcasecmp((const char*) pMimeType->GetBuffer(), REALVIDEO_MULTIRATE_MIME_TYPE) == 0)))
  140. {
  141.     m_bEndOneRuleEndAll = TRUE;
  142. }
  143. HX_RELEASE(pMimeType);
  144.     }
  145.     /* Extract RuleBook from the stream header */
  146.     IHXBuffer* pRuleBook = NULL;
  147.     m_pHeader->GetPropertyCString("ASMRuleBook", pRuleBook);
  148.     if (pRuleBook)
  149.     {
  150.         m_pRuleBook = new ASMRuleBook ((const char *)pRuleBook->GetBuffer());
  151. m_nNumRules = m_pRuleBook->GetNumRules();
  152. m_ulRuleBw = new UINT32[m_nNumRules];
  153. m_ulRulePreData = new UINT32[m_nNumRules];
  154. m_bRuleTimeStampDelivery = new BOOL[m_nNumRules];
  155. m_pSubInfo = new BOOL[m_nNumRules];
  156. m_pRuleSubscribeStatus = new BOOL[m_nNumRules];
  157.         for (UINT16 i = 0; i < m_nNumRules; i++)
  158.         {
  159.     IHXValues* pValues;
  160.     IHXBuffer* pBuffer;
  161.     m_pRuleBook->GetProperties(i, pValues);
  162.     m_ulRuleBw[i] = 0;
  163.     m_ulRulePreData[i] = 0;
  164.     m_bRuleTimeStampDelivery[i] = FALSE;
  165.     if (HXR_OK == pValues->GetPropertyCString("PreData",
  166. pBuffer))
  167.     {
  168. m_ulRulePreData[i] = atoi((char*)pBuffer->GetBuffer());
  169. pBuffer->Release();
  170.     }
  171.     if (HXR_OK == pValues->GetPropertyCString("AverageBandwidth",
  172. pBuffer))
  173.     {
  174. m_ulRuleBw[i] = atoi((char*)pBuffer->GetBuffer());
  175. pBuffer->Release();
  176.     }
  177.     else if (HXR_OK == pValues->GetPropertyCString("TimeStampDelivery",
  178. pBuffer))
  179.     {
  180. if ((pBuffer->GetBuffer()[0] == 'T') ||
  181.     (pBuffer->GetBuffer()[0] == 't'))
  182. {
  183.     // Handle TimeStamp Delivery (i.e. assume significant bandwidth)
  184.     m_ulRuleBw[i] = 0;
  185.     m_bRuleTimeStampDelivery[i] = TRUE;
  186. }
  187. pBuffer->Release();
  188.     }
  189.     else
  190.     {
  191. /* XXXSMP Temporary hack for invalid rulebooks */
  192. if (i == 0)
  193. {
  194.     IHXValues* pHeader = 0;
  195.     HX_VERIFY(pHeader = pStream->GetHeader());
  196.     pHeader->GetPropertyULONG32("AvgBitRate",m_ulRuleBw[i]);
  197.     pHeader->Release();
  198. }
  199. else
  200. {
  201.     m_ulRuleBw[i] = 0;
  202. }
  203.     }
  204.     pValues->Release();
  205.             m_pSubInfo[i] = 0;
  206.     m_pRuleSubscribeStatus[i] = FALSE;
  207.         }
  208. BOOL bFixed = TRUE;
  209. m_bHasExpression = m_pRuleBook->HasExpression();
  210. if (m_bHasExpression == FALSE)
  211. {
  212.     UINT16 i;
  213.     for (i = 0; i < m_nNumRules; i++)
  214.     {
  215. if (m_bRuleTimeStampDelivery[i] == FALSE)
  216. {
  217.     bFixed = FALSE;
  218.     break;
  219. }
  220.     }
  221.     if (bFixed)
  222.     {
  223. m_ulFixedBandwidth = 1;
  224.     }
  225.     else
  226.     {
  227. m_ulCurrentBandwidth = 0;
  228. for (i = 0; i < m_nNumRules; i++)
  229. {
  230.     m_ulCurrentBandwidth += m_ulRuleBw[i];
  231. }
  232. m_ulFixedBandwidth = m_ulCurrentBandwidth;
  233.     }
  234. }
  235.     }
  236.     else
  237.     {
  238. IHXValues* pHeader = 0;
  239. HX_VERIFY(pHeader = pStream->GetHeader());
  240. HX_VERIFY(HXR_OK == pHeader->GetPropertyULONG32("AvgBitRate",
  241.     m_ulFixedBandwidth));
  242. m_ulCurrentBandwidth = m_ulFixedBandwidth; 
  243. pHeader->Release();
  244.     }
  245.     /* Get Registry ID's for interesting properties */
  246.     IHXBuffer* pPropName = 0;
  247.     // init. 
  248.     memset(m_szRecv, 0, MAX_DISPLAY_NAME);
  249.     memset(m_szLost, 0, MAX_DISPLAY_NAME);
  250.     memset(m_szClipBandwidth, 0, MAX_DISPLAY_NAME);
  251.     if( m_pRegistry )
  252. {
  253.     m_pRegistry->GetPropName(ulStreamID, pPropName);
  254. }
  255.     
  256.     if (pPropName)
  257.     {
  258. SafeSprintf(m_szRecv, MAX_DISPLAY_NAME, "%s.received", pPropName->GetBuffer());
  259. m_ulIDRecv = m_pRegistry->GetId(m_szRecv);
  260. SafeSprintf(m_szLost, MAX_DISPLAY_NAME, "%s.lost", pPropName->GetBuffer());
  261. m_ulIDLost = m_pRegistry->GetId(m_szLost);
  262. SafeSprintf(m_szClipBandwidth, MAX_DISPLAY_NAME, "%s.ClipBandwidth", pPropName->GetBuffer());
  263. m_ulIDClipBandwidth = m_pRegistry->GetId(m_szClipBandwidth);
  264. pPropName->Release();
  265.     }
  266.     /* 
  267.      * We consider Local source as a Network source IFF someone uses core
  268.      * for simulated network playback (used for Preview mode in the Encoder)
  269.      */
  270.     if (pSource->IsLocalSource() && !pSource->IsSimulatedNetworkPlayback())
  271.     {
  272. /* Some large bandwidth */
  273. m_ulBandwidthAllocation = 0x7FFFFFFF;
  274. BOOL b;
  275. SetBandwidthUsage(m_ulBandwidthAllocation, b);
  276.     }
  277.     else if (pSource->IsPNAProtocol())
  278.     {
  279. IHXBuffer* pMimeType = NULL;
  280. m_pHeader->GetPropertyCString("MimeTYpe", pMimeType);
  281. if (pMimeType && 
  282.     ::strcasecmp((const char*) pMimeType->GetBuffer(), "audio/x-pn-realaudio") == 0)
  283. {
  284.     /* Some large bandwidth */
  285.     m_ulBandwidthAllocation = 0x7FFFFFFF;
  286.     BOOL b;
  287.     SetBandwidthUsage(m_ulBandwidthAllocation, b);
  288. }
  289. HX_RELEASE(pMimeType);
  290.     }
  291.     else if (pRuleBook)
  292.     {
  293. m_pLossCB = new LossCheckCallback(this);
  294. m_pLossCB->AddRef();
  295. m_ulLossCBHandle = m_pScheduler->RelativeEnter(m_pLossCB, 1000);
  296.     }
  297.     
  298.     HX_RELEASE(pRuleBook);
  299. }
  300. HXASMStream::~HXASMStream()
  301. {
  302. #ifndef GOLD
  303.     HX_RELEASE(m_pEM);
  304. #endif
  305.     if (m_ulLossCBHandle)
  306.     {
  307.         m_pScheduler->Remove(m_ulLossCBHandle);
  308.         m_ulLossCBHandle = 0;
  309.     }
  310.     HX_RELEASE(m_pLossCB);
  311.     HX_VECTOR_DELETE(m_pSubInfo);
  312.     HX_VECTOR_DELETE(m_ulRuleBw);
  313.     HX_VECTOR_DELETE(m_ulRulePreData);
  314.     HX_VECTOR_DELETE(m_bRuleTimeStampDelivery);
  315.     HX_VECTOR_DELETE(m_pRuleSubscribeStatus);
  316.     
  317.     HX_RELEASE(m_pASMSource);
  318.     HX_RELEASE(m_pAtomicRuleChange);
  319.     HX_RELEASE(m_pSource);
  320.     HX_RELEASE(m_pHeader);
  321.     HX_RELEASE(m_pRegistry);
  322.     HX_RELEASE(m_pScheduler);
  323.     CHXMapPtrToPtr::Iterator lIterator =  m_pStreamSinkMap->Begin();
  324.     for (; lIterator != m_pStreamSinkMap->End(); ++lIterator)
  325.     {
  326. IHXASMStreamSink* pASMStreamSink = 
  327. (IHXASMStreamSink*) *lIterator;
  328. pASMStreamSink->Release();
  329.     }
  330.     m_pStreamSinkMap->RemoveAll();
  331.     HX_DELETE(m_pASMRuleState);
  332.     HX_DELETE(m_pRuleBook);
  333.     HX_RELEASE(m_pSubscriptionVariables);
  334.     HX_DELETE(m_pStreamSinkMap);
  335. }
  336. STDMETHODIMP_(UINT32)
  337. HXASMStream::AddRef(void)
  338. {
  339.     return InterlockedIncrement(&m_lRefCount);
  340. }
  341. STDMETHODIMP_(UINT32)
  342. HXASMStream::Release(void)
  343. {
  344.     if (InterlockedDecrement(&m_lRefCount) > 0)
  345.     {
  346. return m_lRefCount;
  347.     }
  348.     delete this;
  349.     return 0;
  350. }
  351. STDMETHODIMP
  352. HXASMStream::QueryInterface
  353. (
  354.     REFIID interfaceID,
  355.     void** ppInterfaceObj
  356. )
  357. {
  358.     QInterfaceList qiList[] =
  359.         {
  360.             { GET_IIDHANDLE(IID_IHXASMStream), (IHXASMStream*)this },
  361.             { GET_IIDHANDLE(IID_IHXASMStream2), (IHXASMStream2*)this },
  362.             { GET_IIDHANDLE(IID_IHXStreamBandwidthNegotiator), (IHXStreamBandwidthNegotiator*)this },
  363.             { GET_IIDHANDLE(IID_IHXStreamBandwidthBias), (IHXStreamBandwidthBias*)this },
  364.             { GET_IIDHANDLE(IID_IHXASMProps), (IHXASMProps*)this },
  365.             { GET_IIDHANDLE(IID_IHXAtomicRuleGather), (IHXAtomicRuleGather*)this },
  366.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXASMStream*)this },
  367.         };
  368.     
  369.     return ::QIFind(qiList, QILISTSIZE(qiList), interfaceID, ppInterfaceObj);
  370. }
  371. /*
  372.  * IHXASMStream methods
  373.  */
  374. /************************************************************************
  375.  * Method:
  376.  *     IHXASMStream::AddStreamSink
  377.  * Purpose:
  378.  *
  379.  */
  380. STDMETHODIMP
  381. HXASMStream::AddStreamSink(IHXASMStreamSink* pASMStreamSink)
  382. {
  383.     HX_ASSERT(pASMStreamSink);
  384.     if (!pASMStreamSink)
  385.     {
  386. return HXR_UNEXPECTED;
  387.     }
  388.     void* pTmp;
  389.     if (m_pStreamSinkMap->Lookup((void*) pASMStreamSink, pTmp))
  390.     {
  391. return HXR_UNEXPECTED;
  392.     }
  393.     pASMStreamSink->AddRef();
  394.     m_pStreamSinkMap->SetAt((void*) pASMStreamSink, (void*) pASMStreamSink);
  395.     return HXR_OK;
  396. }
  397. /************************************************************************
  398.  * Method:
  399.  *     IHXASMStream::RemoveStreamSink
  400.  * Purpose:
  401.  *
  402.  */
  403. STDMETHODIMP
  404. HXASMStream::RemoveStreamSink(IHXASMStreamSink* pASMStreamSink)
  405. {
  406.     HX_ASSERT(pASMStreamSink && m_pASMSource);
  407.     if (!pASMStreamSink)
  408.     {
  409. return HXR_UNEXPECTED;
  410.     }
  411.     void* pTmp;
  412.     if (!m_pStreamSinkMap->Lookup((void*) pASMStreamSink, pTmp))
  413.     {
  414. return HXR_UNEXPECTED;
  415.     }
  416.     pASMStreamSink->Release();
  417.     m_pStreamSinkMap->RemoveKey((void*) pASMStreamSink);
  418.     return HXR_OK;
  419. }
  420. STDMETHODIMP
  421. HXASMStream::Subscribe(UINT16 uRuleNumber)
  422. {
  423.     HX_RESULT lResult = HXR_OK;
  424.     if (!m_pASMSource)
  425.     {
  426. return HXR_OK;
  427.     }
  428.     DEBUG_OUT(m_pEM, DOL_ASM, (s, "(%p)Subscribe: Stream=%d Rule=%d", m_pSource, m_uStreamNumber, uRuleNumber));
  429.     m_pRuleSubscribeStatus[uRuleNumber] = TRUE;
  430.     
  431.     if (m_pASMRuleState)
  432.     {
  433. m_pASMRuleState->CompleteSubscribe(uRuleNumber);
  434. m_pASMRuleState->StartUnsubscribePending(uRuleNumber);
  435.     }
  436.     if (m_pAtomicRuleChange)
  437.     {
  438. lResult = HXR_OK;
  439.     }
  440.     else
  441.     {
  442. lResult = m_pASMSource->Subscribe(m_uStreamNumber, uRuleNumber); 
  443.     }
  444.     if (lResult == HXR_OK)
  445.     {
  446. CHXMapPtrToPtr::Iterator lIterator =  m_pStreamSinkMap->Begin();
  447. for (; (lIterator != m_pStreamSinkMap->End()) && lResult == HXR_OK; 
  448. ++lIterator)
  449. {
  450.     IHXASMStreamSink* pASMStreamSink = 
  451.     (IHXASMStreamSink*) *lIterator;
  452.     lResult = pASMStreamSink->OnSubscribe(uRuleNumber);
  453. }
  454.     }
  455.     
  456.     return lResult;
  457. }
  458. STDMETHODIMP
  459. HXASMStream::Unsubscribe(UINT16 uRuleNumber)
  460. {
  461.     HX_RESULT lResult = HXR_OK;
  462.     if (!m_pASMSource)
  463.     {
  464. return HXR_OK;
  465.     }
  466.     DEBUG_OUT(m_pEM, DOL_ASM, (s, "(%p)Unsubscribe: Stream=%d Rule=%d", m_pSource, m_uStreamNumber, uRuleNumber));
  467.     m_pRuleSubscribeStatus[uRuleNumber] = FALSE;
  468.     
  469.     if (m_pASMRuleState)
  470.     {
  471. m_pASMRuleState->CompleteUnsubscribe(uRuleNumber);
  472.     }
  473.     if (m_pAtomicRuleChange)
  474.     {
  475. lResult = HXR_OK;
  476.     }
  477.     else
  478.     {
  479. lResult = m_pASMSource->Unsubscribe(m_uStreamNumber, uRuleNumber); 
  480.     }
  481.     if (lResult == HXR_OK)
  482.     {
  483. CHXMapPtrToPtr::Iterator lIterator =  m_pStreamSinkMap->Begin();
  484. for (; (lIterator != m_pStreamSinkMap->End()) && lResult == HXR_OK; 
  485. ++lIterator)
  486. {
  487.     IHXASMStreamSink* pASMStreamSink = 
  488.     (IHXASMStreamSink*) *lIterator;
  489.     lResult = pASMStreamSink->OnUnsubscribe(uRuleNumber);
  490. }
  491.     }
  492.     
  493.     return lResult;
  494. }
  495. /*
  496.  * This is actually just a negotiation interface.  We need an interface
  497.  * that tells us the actual allotment after oversend so that we can have
  498.  * some more bandwidth available in case something like this happens:
  499.  *  0 - 8k
  500.  *  1 - 16k
  501.  *  2 - 1k ECC for 0
  502.  *  3 - 2k ECC for 1
  503.  *  In this case, we need extra bandwidth already available to go and
  504.  *  add 3 to 1
  505.  */
  506. STDMETHODIMP
  507. HXASMStream::SetBandwidthUsage(REF(UINT32) ulRecvBitRate,
  508.        REF(BOOL) bTimeStampDelivery)
  509. {
  510.     if (m_pRuleBook == NULL)
  511.     {
  512. return HXR_OK;
  513.     }
  514.     m_ulBandwidthAllocation = ulRecvBitRate;
  515.     /*
  516.      * This appears to be a var to make sure that Recalc only
  517.      * does things when called from certain places.  I am not sure.
  518.      */
  519.     m_bStartRecalc = TRUE;
  520.     Recalc();
  521.     /* 
  522.      *  Add up the bitrate of all of the rules we are subscribed to 
  523.      *  and check if any of the rules put us in time stamped delivery mode.
  524.      */
  525.     ulRecvBitRate = 0;
  526.     m_bTimeStampDeliveryMode = FALSE;
  527.     for (UINT16 i = 0; i < m_nNumRules; i++)
  528.     {
  529. if (m_pSubInfo[i])
  530. {
  531.     ulRecvBitRate += m_ulRuleBw[i];
  532.     if(m_bRuleTimeStampDelivery[i])
  533.     {
  534. m_bTimeStampDeliveryMode = TRUE;
  535.     }     
  536. }
  537.     }
  538.     bTimeStampDelivery = m_bTimeStampDeliveryMode;
  539.     return HXR_OK;
  540. }
  541. STDMETHODIMP
  542. HXASMStream::HandleSlowSource(UINT32 ulRecvBitRate)
  543. {
  544. #if XXXSMP
  545.     /* Whoa!  This code is totally buggy.  We need to fix this!
  546.      *
  547.      * This code was NEVER executed, since day 1.  Since I fixed the TS
  548.      * delivery flag above, we started executing it (and it doesn't work).
  549.      *
  550.      * Besides, not executing it is a good thing-  This mode really sucks.
  551.      */
  552.     if (m_bTimeStampDeliveryMode)
  553. #else
  554.     if (0)
  555. #endif
  556.     {
  557.     /*
  558.      *  Time stamp delivery mode.  No amount of ASM can help us now.
  559.      */    
  560. /*
  561.  * If we are above what we previously asked the server to limit to
  562.  * then we have not yet started receiving the slower data yet or 
  563.  * the server is ignoring us.  Either way it will not help to send
  564.  * the message again.
  565.  */
  566. if(ulRecvBitRate >= m_ulLastLimitBandwidth)
  567. {
  568.     return HXR_OK;
  569. }
  570. IHXThinnableSource* pThin;
  571. if(HXR_OK == m_pASMSource->QueryInterface(IID_IHXThinnableSource,
  572. (void **)&pThin))
  573. {
  574.     /*
  575.      *  Tell the source to thin the bitrate down to 80% of what we
  576.      *  were getting.
  577.      */
  578.     m_ulLastLimitBandwidth = (UINT32)(0.8 * ulRecvBitRate);
  579.     pThin->LimitBandwidthByDropping(m_uStreamNumber, m_ulLastLimitBandwidth);
  580.     pThin->Release();
  581. }
  582.     }
  583.     return HXR_OK;
  584. }
  585. STDMETHODIMP
  586. HXASMStream::GetThresholdInfo(float* pThreshold, REF(UINT32) ulNumThreshold)
  587. {
  588.     // XXXSMP Fix this.  Unify all construction of buffers & values
  589.     // to one place.  Don't reconstruct unless you need to and store wasting
  590.     // time, space, memory!
  591.     if (!m_pRuleBook)
  592.     {
  593. // ASM always expect num of threshold >= 1
  594. ulNumThreshold = 1;
  595. pThreshold[0] = 0.0f;
  596. return HXR_OK;
  597.     }
  598.     HXSMUpdateSubscriptionVars(m_pSubscriptionVariables, 0, 
  599.        TRUE, ComputeLost());
  600.     m_pRuleBook->GetPreEvaluate(pThreshold, ulNumThreshold,
  601.     m_pSubscriptionVariables, "Bandwidth");
  602.     return HXR_OK;
  603. }
  604. STDMETHODIMP
  605. HXASMStream::UnRegister(void)
  606. {
  607.     m_bStartRecalc = FALSE;
  608.     /* Remove any scheduled callback */
  609.     if (m_ulLossCBHandle && m_pLossCB && m_pScheduler)
  610.     {
  611.         m_pScheduler->Remove(m_ulLossCBHandle);
  612.         m_ulLossCBHandle = 0;
  613.     }
  614.   
  615.     return HXR_OK;
  616. }
  617. STDMETHODIMP_(ULONG32)
  618. HXASMStream::GetNumThresholds(void)
  619. {
  620.     // return the maximum number of thresholds for this rulebook
  621.     return m_pRuleBook ? m_pRuleBook->GetNumThresholds(): 0;
  622. }
  623. STDMETHODIMP
  624. HXASMStream::GetFixedBandwidth(REF(UINT32) ulBitRate)
  625. {
  626.     if (m_ulFixedBandwidth)
  627.     {
  628. ulBitRate = m_ulFixedBandwidth;
  629. return HXR_OK;
  630.     }
  631.     return HXR_FAIL;
  632. }
  633. STDMETHODIMP
  634. HXASMStream::GetBiasFactor(REF(INT32) lBias)
  635. {
  636.     lBias = m_lBias;
  637.     return HXR_OK;
  638. }
  639. STDMETHODIMP
  640. HXASMStream::SetBiasFactor(INT32 lBias)
  641. {
  642.     m_lBias = lBias;
  643.     return HXR_OK;
  644. }
  645. HXASMStream::LossCheckCallback::LossCheckCallback(HXASMStream* pASMStream)
  646. {
  647.     m_pASMStream    = pASMStream;
  648.     m_lRefCount     = 0;
  649. }
  650. STDMETHODIMP_(UINT32)
  651. HXASMStream::LossCheckCallback::AddRef(void)
  652. {
  653.     return InterlockedIncrement(&m_lRefCount);
  654. }
  655. STDMETHODIMP_(UINT32)
  656. HXASMStream::LossCheckCallback::Release(void)
  657. {
  658.     if (InterlockedDecrement(&m_lRefCount) > 0)
  659.     {
  660. return m_lRefCount;
  661.     }
  662.     delete this;
  663.     return 0;
  664. }
  665. STDMETHODIMP
  666. HXASMStream::LossCheckCallback::QueryInterface
  667. (
  668.     REFIID interfaceID,
  669.     void** ppInterfaceObj
  670. )
  671. {
  672.     QInterfaceList qiList[] =
  673.         {
  674.             { GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*)this },
  675.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXCallback*)this },
  676.         };
  677.     
  678.     return ::QIFind(qiList, QILISTSIZE(qiList), interfaceID, ppInterfaceObj);
  679. }
  680. STDMETHODIMP
  681. HXASMStream::GetPreData(REF(UINT32) ulPreData)
  682. {
  683.     if (m_ulCurrentPreData)
  684.     {
  685. ulPreData = m_ulCurrentPreData;
  686. return HXR_OK;
  687.     }
  688.     else
  689.     {
  690. ulPreData = 0;
  691. return HXR_FAIL;
  692.     }
  693. }
  694. STDMETHODIMP
  695. HXASMStream::GetBandwidth(REF(UINT32) ulBandwidth)
  696. {
  697.     if (m_ulCurrentBandwidth)
  698.     {
  699. ulBandwidth = m_ulCurrentBandwidth;
  700. return HXR_OK;
  701.     }
  702.     else if (m_ulLastBandwidth)
  703.     {
  704. ulBandwidth = m_ulLastBandwidth;
  705. return HXR_OK;
  706.     }
  707.     else
  708.     {
  709. ulBandwidth = 0;
  710. return HXR_FAILED;
  711.     }
  712. }
  713. void
  714. HXASMStream::RecalcCurrentProps()
  715. {
  716.     m_ulCurrentBandwidth    = 0;
  717.     m_ulCurrentPreData     = 0;
  718.     for (UINT16 i = 0; i < m_nNumRules; i++)
  719.     {
  720.         if (m_pSubInfo[i])
  721.         {
  722.     m_ulCurrentPreData  += m_ulRulePreData[i];
  723.     m_ulCurrentBandwidth += m_ulRuleBw[i];
  724. }
  725.     }
  726.     if (m_pSource->IsActive())
  727.     {
  728. INT32  lLastBandwidth = 0;
  729.     if( m_pRegistry )
  730. {
  731.         m_pRegistry->GetIntById(m_ulIDClipBandwidth, lLastBandwidth);
  732. }
  733. /* Do not override bandwidth if the current bandwidth has either
  734.  * not changed or is zero.
  735.  */
  736. if (m_ulCurrentBandwidth != 0 && 
  737.     (UINT32) lLastBandwidth != m_ulCurrentBandwidth && 
  738. m_pRegistry)
  739. {
  740.     m_pRegistry->SetIntById(m_ulIDClipBandwidth, m_ulCurrentBandwidth);
  741.     /* A hack to tell the top level client that a stream switch occured */
  742.     m_pRegistry->SetIntByName("Statistics.StreamSwitchOccured", 1);
  743. }
  744.     }
  745.     if (m_ulCurrentBandwidth > 0)
  746.     {
  747. m_ulLastBandwidth = m_ulCurrentBandwidth;
  748.     }
  749.     
  750. //DEBUG_OUT(this, (s, "New PreData %p %d New Bandwidth %dn", this, m_ulCurrentPreData, m_ulCurrentBandwidth));
  751. }
  752. void
  753. HXASMStream::Recalc()
  754. {
  755.     if (!m_bStartRecalc)
  756. return;
  757.     HXSMUpdateSubscriptionVars(m_pSubscriptionVariables, 
  758.        m_ulBandwidthAllocation, 
  759.        TRUE, ComputeLost());
  760.     BOOL* pCurrentSubInfo = new BOOL[m_nNumRules];
  761.     
  762.     if (m_pRuleBook)
  763.     {
  764. HX_RESULT lResult = m_pRuleBook->GetSubscription(pCurrentSubInfo, m_pSubscriptionVariables);
  765. HX_ASSERT(lResult == HXR_OK);
  766.     }
  767.     CHXSimpleList SubChange;
  768.     CHXSimpleList* pSubList = &SubChange;
  769.     if (m_pSubList)
  770.     {
  771. pSubList = m_pSubList;
  772.     }
  773.     for (UINT16 i = 0; i < m_nNumRules; i++)
  774.     {
  775.         if (pCurrentSubInfo[i] != m_pSubInfo[i])
  776.         {
  777.     RTSPSubscription* pEntry = NULL;
  778.     if (m_pAtomicRuleChange)
  779.     {
  780. pEntry = new RTSPSubscription;
  781. pEntry->m_streamNumber = m_uStreamNumber;
  782. pEntry->m_ruleNumber = i;
  783. pEntry->m_bIsSubscribe = (pCurrentSubInfo[i]) ? TRUE : FALSE;
  784. pSubList->AddTail(pEntry);
  785.     }
  786.             if (pCurrentSubInfo[i])
  787.     {
  788.                 Subscribe(i);
  789.     }
  790.             else
  791.     {
  792.                 Unsubscribe(i);
  793.     }
  794.             m_pSubInfo[i] = pCurrentSubInfo[i];
  795.         }
  796.     }
  797.     if (m_pAtomicRuleChange && (!m_pSubList) && (!SubChange.IsEmpty()))
  798.     {
  799. m_pAtomicRuleChange->RuleChange(SubChange);
  800.     }
  801.     RecalcCurrentProps();
  802.     delete [] pCurrentSubInfo;
  803.     /* Reschedule callback if this was invoked by the scheduler callback */
  804.     if (!m_ulLossCBHandle && m_pLossCB)
  805.     {
  806. m_ulLossCBHandle = m_pScheduler->RelativeEnter(m_pLossCB, 1000);
  807.     }
  808. }
  809. float HXASMStream::ComputeLost()
  810. {
  811.     INT32 ulRecv = 0, ulLost = 0;
  812.     float lost = 0.0;
  813.     
  814.     if( m_pRegistry )
  815.     {
  816.         m_pRegistry->GetIntById(m_ulIDRecv, ulRecv);
  817.         m_pRegistry->GetIntById(m_ulIDLost, ulLost);
  818.     }
  819.     if (ulRecv != 0)
  820.     {
  821. lost = ((float)ulLost) / ((float)ulRecv) * 100;
  822.     }
  823.     return lost;
  824. }
  825. STDMETHODIMP
  826. HXASMStream::LossCheckCallback::Func()
  827. {
  828.     m_pASMStream->m_ulLossCBHandle = 0;
  829.     m_pASMStream->Recalc();
  830.     return HXR_OK;
  831. }
  832. HX_RESULT
  833. HXASMStream::ResetASMSource(IHXASMSource* pASMSource)
  834. {
  835.     HX_RESULT hr = HXR_OK;
  836.     HX_RELEASE(m_pASMSource);
  837.     if (pASMSource)
  838.     {
  839. pASMSource->QueryInterface(IID_IHXASMSource, (void **)&m_pASMSource);
  840.     }
  841.     if (m_pAtomicRuleChange)
  842.     {
  843. HX_RELEASE(m_pAtomicRuleChange);
  844. pASMSource->QueryInterface(IID_IHXAtomicRuleChange,
  845.     (void **)&m_pAtomicRuleChange);
  846.     }
  847.     // reset substream info.
  848.     if (m_pRuleBook && m_pSubInfo)
  849.     {
  850. for (UINT16 i = 0; i < m_nNumRules; i++)
  851. {
  852.     m_pSubInfo[i] = 0;
  853. }
  854.     }
  855.     // reset Registry ID
  856.     if (strlen(m_szRecv) && m_pRegistry)
  857.     {
  858. m_ulIDRecv = m_pRegistry->GetId(m_szRecv);
  859.     }
  860.     if (strlen(m_szLost) && m_pRegistry)
  861.     {
  862. m_ulIDLost = m_pRegistry->GetId(m_szLost);
  863.     }
  864.     if (strlen(m_szClipBandwidth) && m_pRegistry)
  865.     {
  866. m_ulIDClipBandwidth = m_pRegistry->GetId(m_szClipBandwidth);
  867.     }
  868.     return hr;
  869. }
  870. STDMETHODIMP
  871. HXASMStream::RuleGather(CHXSimpleList* pList)
  872. {
  873.     /* Truely disgusting... */
  874.     m_pSubList = pList;
  875.     return HXR_OK;
  876. }
  877. STDMETHODIMP
  878. HXASMStream::RuleFlush(CHXSimpleList* pList)
  879. {
  880.     m_pAtomicRuleChange->RuleChange(*pList);
  881.     return HXR_OK;
  882. }
  883. void
  884. HXASMStream::PostEndTimePacket(IHXPacket* pPacket, BOOL& bSentMe, BOOL& bEndMe)
  885. {
  886.     int i = 0;
  887.     UINT8 nRuleFlags = 0;
  888.     UINT16 nRuleNumber = 0;
  889.     IHXBuffer* pRuleBook = NULL;
  890.     bSentMe = TRUE;
  891.     bEndMe = FALSE;
  892.     // assume the packet is NOT lost
  893.     HX_ASSERT(pPacket->IsLost() == FALSE);
  894.     // This is the first packet whose timestamp > endtime
  895.     // Initialize ASMRuleState to determine whether pass it to
  896.     // the renderer or not
  897.     if (!m_pASMRuleState)
  898.     {
  899. // Extract RuleBook from the stream header
  900. m_pHeader->GetPropertyCString("ASMRuleBook", pRuleBook);     
  901. if (pRuleBook != NULL)
  902. {
  903.     m_pASMRuleState = new CASMRuleState(m_nNumRules, (char*)pRuleBook->GetBuffer(), (UINT16)pRuleBook->GetSize());
  904. }
  905. if (m_pASMRuleState)
  906. {
  907.     // initialize the ASMRuleState based on the 
  908.     // current subscription status of all the rules
  909.     for (i = 0; i < m_nNumRules; i++)
  910.     {
  911. if (m_pRuleSubscribeStatus[i])
  912. {
  913.     m_pASMRuleState->CompleteSubscribe(i);
  914.     m_pASMRuleState->StartUnsubscribePending(i);
  915. }
  916.     }
  917. }
  918. else
  919. {
  920.     // end the stream now is fine.
  921.     bSentMe = FALSE;
  922.     bEndMe = TRUE;
  923.     goto cleanup;
  924. }
  925.     }
  926.     nRuleNumber = pPacket->GetASMRuleNumber();
  927.     nRuleFlags = pPacket->GetASMFlags();
  928.     // if the rule is unsubscribed, then
  929.     // we just pass it to the renderer since
  930.     // the server will stop sending them anyway
  931.     // i.e. during the stream swithing
  932.     if (!m_pRuleSubscribeStatus[nRuleNumber] &&
  933. m_pASMRuleState->AnyPendingUnsubscribes())
  934.     {
  935. goto cleanup;
  936.     }    
  937.     else if (nRuleFlags & HX_ASM_SWITCH_OFF)
  938.     {
  939. if (m_pASMRuleState->IsUnsubscribePending(nRuleNumber) &&
  940.     m_pASMRuleState->CanUnsubscribeNow(nRuleNumber))
  941. {
  942.     m_pASMRuleState->CompleteUnsubscribe(nRuleNumber);
  943. }
  944.     }
  945.     bSentMe = m_pASMRuleState->IsRuleSubscribed(nRuleNumber);
  946.     // if all the rules are unsubscribed, then 
  947.     // we are DONE!
  948.     if (!m_pASMRuleState->AnyPendingUnsubscribes())
  949.     {
  950. bSentMe = FALSE;
  951. bEndMe = TRUE;
  952.     }
  953.     else if (bSentMe == FALSE && m_bEndOneRuleEndAll)
  954.     {
  955. bEndMe = TRUE;
  956.     }
  957. cleanup:
  958.     HX_RELEASE(pRuleBook);
  959.     return;
  960. }
  961. void
  962. HXASMStream::ResetASMRuleState(void)
  963. {
  964.     HX_DELETE(m_pASMRuleState);
  965.     return;
  966. }
  967. STDMETHODIMP_(HX_RESULT)
  968. HXASMStream::Enable( UINT16 nRule )
  969. {
  970.    if( m_pRuleBook )
  971.    {
  972.       m_pRuleBook->Enable( nRule );
  973.    }
  974.    return HXR_OK;
  975. }
  976. STDMETHODIMP_(HX_RESULT)
  977. HXASMStream::Disable( UINT16 nRule )
  978. {
  979.    if( m_pRuleBook )
  980.    {
  981.       m_pRuleBook->Disable( nRule );
  982.    }
  983.     return HXR_OK;
  984. }
  985. STDMETHODIMP_(HX_RESULT)
  986. HXASMStream::ReCompute()
  987. {
  988.    HX_RESULT retVal = HXR_OK;
  989.    if( m_pRuleBook )
  990.    {
  991.       m_pRuleBook->ReCompute();
  992.       // Now we must check that there is at least 1 playable substream.
  993.       BOOL* pCurrentSubInfo = new BOOL[m_nNumRules];
  994.       if( pCurrentSubInfo == NULL )
  995.       {
  996.           return HXR_FAIL;
  997.       }
  998.           
  999.       HXSMUpdateSubscriptionVars(m_pSubscriptionVariables, 0, FALSE, 0);
  1000.       // GetSubscription does not actually do any subscribing. Rather it 
  1001.       // populates the boolean array pCurrentSubInfo such that subscribable
  1002.       // streams are set to TRUE;
  1003.       m_pRuleBook->GetSubscription( pCurrentSubInfo, m_pSubscriptionVariables );
  1004.       BOOL bAtLeastOneRuleSubscribable = FALSE;
  1005.       for( int ii=0; ii<m_nNumRules; ii++ )
  1006.       {
  1007.           if( pCurrentSubInfo[ii] == TRUE )
  1008.           {
  1009.               bAtLeastOneRuleSubscribable = TRUE;
  1010.           }
  1011.       }
  1012.       HX_VECTOR_DELETE(pCurrentSubInfo);
  1013.       if( bAtLeastOneRuleSubscribable == FALSE )
  1014.       {
  1015.           // We can't subscribe to any stream so reset and fail.
  1016.           for( int ii=0; ii<m_nNumRules; ii++ )
  1017.           {
  1018.               m_pRuleBook->Enable( ii );
  1019.           }
  1020.           m_pRuleBook->ReCompute();
  1021.           retVal = HXR_FAIL;
  1022.       }
  1023.    }
  1024.    return retVal;
  1025. }