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

Symbian

开发平台:

Visual C++

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