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

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 "hxtypes.h"
  36. #include "hxcom.h"
  37. #ifdef _WINDOWS
  38. #include <windows.h>
  39. #endif
  40. #include "hlxclib/stdio.h"
  41. #include "hlxclib/stdlib.h"
  42. #include "prefdefs.h"
  43. #include "plprefk.h"
  44. #include "hxcomm.h"
  45. #include "ihxpckts.h"
  46. #include "hxfiles.h"
  47. #include "hxengin.h"
  48. #include "hxcore.h"
  49. #include "hxprefs.h"
  50. #include "hxpref.h"
  51. #include "hxausvc.h"
  52. #include "hxmon.h"
  53. #include "hxclreg.h"
  54. #include "hxgroup.h"
  55. #include "hxsmbw.h"
  56. #include "hxstrm.h"
  57. #include "hxwin.h"
  58. #include "hxcore.h"
  59. #include "hxhyper.h"
  60. #include "playhpnv.h"
  61. #include "hxplugn.h"
  62. #include "hxrendr.h"
  63. #include "chxeven.h"
  64. #include "chxelst.h"
  65. #include "hxmap.h"
  66. #include "hxrquest.h"
  67. #include "hxmangle.h"
  68. #include "hxtick.h"
  69. #include "dbcs.h"
  70. #include "hxstrutl.h"
  71. #include "strminfo.h"
  72. #include "timeval.h"
  73. #include "statsmgr.h"
  74. #include "hxbsrc.h"
  75. #include "hxsrc.h"
  76. #include "srcinfo.h"
  77. #include "corshare.h"
  78. #include "upgrdcol.h"
  79. #include "hxrasyn.h"
  80. #include "hxaudstr.h"
  81. #include "hxplugn.h"
  82. #include "hxrendr.h"
  83. #include "errdbg.h"
  84. // will be taken out once flags are defined in a separate file
  85. #include "rmfftype.h"
  86. #include "hxplay.h"
  87. #include "hxcleng.h"
  88. #include "hxsrc.h"
  89. #include "hxheap.h"
  90. #ifdef _DEBUG
  91. #undef HX_THIS_FILE
  92. static const char HX_THIS_FILE[] = __FILE__;
  93. #endif
  94. #if defined(HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
  95. // TurboPlay should never be turned on in low heap mode, but just in case ...
  96. #define TURBO_AUDIO_PUSHDOWN 100
  97. #else
  98. #define TURBO_AUDIO_PUSHDOWN 2000
  99. #endif
  100. HXSource::HXSource() :
  101.   m_pPlayer (0)
  102. , m_lRefCount(0)
  103. , m_ulStreamIndex(0)
  104. , m_bInitialized (FALSE)
  105. , m_bIsPreBufferingDone(FALSE)
  106. , m_bClipTimeAdjusted(FALSE)
  107. , mLastError (HXR_OK)
  108. , m_ulPerfectPlayTime (0)
  109. , m_ulBufferedPlayTime(0)
  110.         , m_ulStreamHeadersExpected(0)
  111. , m_bPerfectPlayEntireClip(FALSE)
  112. , m_bCannotBufferEntireClip(FALSE)
  113. , m_uNumStreams (0)
  114. , mFlags (0)
  115. , m_bPerfectPlayAllowed (FALSE)
  116. , mSaveAsAllowed (FALSE)
  117. , mLiveStream (FALSE)
  118. , m_bRestrictedLiveStream (FALSE)
  119. , m_bSourceEnd (FALSE)
  120. , m_bForcedSourceEnd(FALSE)
  121. , m_ulPreRollInMs (0)
  122. , m_ulPreRoll (0)
  123. , m_ulAvgBandwidth (0)
  124. , m_ulDuration (0)
  125. , m_bReceivedData (FALSE)
  126. , m_bReceivedHeader(FALSE)
  127. , m_bNonSeekable(FALSE)
  128. , m_nSeeking (0)
  129. , m_bPaused (FALSE)  
  130. , m_bFirstResume(TRUE)
  131. , m_bResumePending(FALSE)
  132. , m_bIsActive(FALSE)
  133. , m_uActiveStreams (0)
  134. , m_pszURL(NULL)
  135. , m_pURL(NULL)
  136. , m_bAltURL(TRUE)
  137. , m_ulStartTime (0)
  138. , m_ulEndTime (0)
  139. , m_ulDelay (0)
  140. , m_ulOriginalDelay (0)
  141. , m_ulPrefetchDelay (0)
  142. , m_llLastExpectedPacketTime(0)
  143. , m_ulRestrictedDuration(0)
  144. , m_bDelayed(FALSE)
  145. , m_ulSourceStartTime(0)
  146. , m_pPreferences (0)
  147. , m_pRegistry (0)
  148. , m_pScheduler (0)
  149. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  150. , m_pStats (0)
  151. , m_pStatsManager(NULL)
  152. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  153. , m_bLocked (FALSE)
  154. , m_pEngine (0)
  155. , m_bRebufferingRequired(FALSE)
  156. , m_bInitialBuffering(TRUE)
  157. , m_bPartOfNextGroup(FALSE)
  158. , m_bPartOfPrefetchGroup(FALSE)
  159. , m_pBufferManager(NULL)
  160. , m_pFileHeader(0)
  161. , m_bPerfectPlay(FALSE)
  162. , m_bBufferedPlay(FALSE)
  163. , m_ulLossHack(0)
  164. , m_ulNumFakeLostPackets(0)
  165. , m_ulLastBufferingCalcTime(0)
  166. , m_pSourceInfo(NULL)
  167. , m_pRequest(NULL)
  168. , m_pASMSource(NULL)
  169. , m_pBackChannel(NULL)
  170. , m_bDefaultAltURL(FALSE)
  171. , m_bCustomEndTime(FALSE)
  172. , m_bCustomDuration(FALSE)
  173. , m_bIsPreBufferingStarted(FALSE)
  174. , m_ulOriginalDuration(0)
  175. , m_bReSetup(FALSE)
  176. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  177. , m_pUpgradeCollection(NULL)
  178. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  179. , m_bRTSPRuleFlagWorkAround(FALSE)
  180.         , m_bContinueWithHeaders(FALSE)
  181. , m_bPrefetch(FALSE)
  182. , m_prefetchType(PrefetchUnknown)
  183. , m_ulPrefetchValue(0)
  184. , m_ulFirstPacketTime(0)
  185. , m_bIsMeta(FALSE)
  186. , m_bFastStart(FALSE)
  187. , m_serverTurboPlay(TURBO_PLAY_UNKNOWN)
  188. , m_ulMaxBandwidth(4000) // 4000kbps
  189. , m_pAudioStreamList(NULL)
  190.         , m_maxPossibleAccelRatio(4.0) // I donno what's a good value?
  191.         , m_ulTurboPushDown(TURBO_AUDIO_PUSHDOWN)
  192.         , m_bSureStreamClip(FALSE)
  193.         , m_ulTurboStartActiveTime(0)
  194. , m_srcEndCode(END_UNKNOWN)
  195. , m_pRecordControl(NULL)
  196. , m_bPlayFromRecordControl(FALSE)
  197.         , m_pRedirectURL(NULL)
  198.         , m_bRedirectPending(FALSE)
  199. {
  200.     mStreamInfoTable = new CHXMapLongToObj;
  201. }
  202. HXSource::~HXSource()
  203. {
  204.     // XXX moved this to the distuctor because we want to keep arround
  205.     // the request until the renderers are close at which point we should
  206.     // be released and deleted.
  207.     HX_RELEASE(m_pRequest);
  208.     HX_VECTOR_DELETE(m_pszURL);
  209.     HX_DELETE(mStreamInfoTable);
  210. }
  211. void
  212. HXSource::Stop()
  213. {
  214.     m_pSourceInfo = NULL;    
  215.     HX_DELETE (m_pURL);
  216.     HX_DELETE (m_pBufferManager);
  217.     if ( FAILED(mLastError) )
  218.     {
  219. HX_RELEASE(m_pRequest);
  220.     }
  221. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  222.     if (m_pStatsManager)
  223.     {
  224. m_pStatsManager->DoCleanup();
  225. HX_RELEASE(m_pStatsManager);
  226.     }        
  227.     HX_DELETE(m_pStats);    
  228. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  229.     DeleteAllEvents(); 
  230.     HX_RELEASE(m_pRegistry);
  231.     HX_RELEASE(m_pPreferences);
  232.     HX_RELEASE(m_pScheduler);
  233.     HX_RELEASE(m_pEngine);
  234. }    
  235. HX_RESULT HXSource::DoCleanup(EndCode endCode)
  236. {
  237.     m_ulDuration = 0;    
  238.     m_ulPreRollInMs = 0;
  239.     m_ulPreRoll = 0;
  240.     m_ulAvgBandwidth = 0;
  241.     m_ulLastBufferingCalcTime = 0;
  242.     m_ulMaxBandwidth = 0;
  243.     m_serverTurboPlay = TURBO_PLAY_UNKNOWN;
  244.     m_bAltURL = FALSE;    
  245.     m_bPaused = FALSE;
  246.     m_bFirstResume = TRUE;
  247.     m_bIsActive = FALSE;
  248.     m_bResumePending = FALSE;
  249.     m_bIsPreBufferingStarted = FALSE;
  250.     m_bIsPreBufferingDone = FALSE;    
  251.     m_bClipTimeAdjusted = FALSE;    
  252.     m_bInitialBuffering = TRUE;
  253.     m_bRebufferingRequired = FALSE;    
  254.     m_bReceivedData = FALSE;
  255.     m_bReceivedHeader = FALSE;
  256.     ReleaseAudioStreams(m_pAudioStreamList);
  257.     HX_DELETE(m_pAudioStreamList);
  258.     DeleteStreamTable();
  259.     CHXSimpleList::Iterator lIter = m_HXStreamList.Begin();
  260.     for (; lIter != m_HXStreamList.End(); ++lIter)
  261.     {
  262. HXStream* pStream = (HXStream*) (*lIter);
  263. pStream->Release();
  264.     }
  265.     m_HXStreamList.RemoveAll();    
  266.     HX_RELEASE(m_pFileHeader);    
  267.     HX_RELEASE(m_pASMSource);
  268.     HX_RELEASE(m_pBackChannel);
  269. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  270.     HX_RELEASE(m_pUpgradeCollection);
  271. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  272.     m_bForcedSourceEnd = FALSE;
  273.     m_bSourceEnd = FALSE;
  274.     HX_DELETE(m_pRedirectURL);
  275.     m_bRedirectPending  = FALSE;
  276. #if defined(HELIX_FEATURE_RECORDCONTROL)
  277.     if(m_pRecordControl)
  278.     {
  279. m_pRecordControl->Cleanup();
  280.     }
  281. #endif /* HELIX_FEATURE_RECORDCONTROL */
  282.     HX_RELEASE(m_pRecordControl);
  283.     return HXR_OK;
  284. }
  285. /////////////////////////////////////////////////////////////////////////
  286. // Method:
  287. // IUnknown::QueryInterface
  288. // Purpose:
  289. // Implement this to export the interfaces supported by your 
  290. // object.
  291. //
  292. STDMETHODIMP HXSource::QueryInterface(REFIID riid, void** ppvObj)
  293. {
  294.     QInterfaceList qiList[] =
  295.         {
  296.             { GET_IIDHANDLE(IID_IHXStreamSource), (IHXStreamSource*)this },
  297.             { GET_IIDHANDLE(IID_IHXPendingStatus), (IHXPendingStatus*)this },
  298.             { GET_IIDHANDLE(IID_IHXInfoLogger), (IHXInfoLogger*)this },
  299.             { GET_IIDHANDLE(IID_IHXPrivateStreamSource), (IHXPrivateStreamSource*)this },
  300.             { GET_IIDHANDLE(IID_IHXSourceBufferingStats), (IHXSourceBufferingStats*)this },
  301.             { GET_IIDHANDLE(IID_IHXSourceBufferingStats2), (IHXSourceBufferingStats2*)this },
  302. #if defined(HELIX_FEATURE_HYPER_NAVIGATE)
  303.             { GET_IIDHANDLE(IID_IHXHyperNavigate), (IHXHyperNavigate*)this },
  304.             { GET_IIDHANDLE(IID_IHXHyperNavigate2), (IHXHyperNavigate2*)this },
  305. #endif /* defined(HELIX_FEATURE_HYPER_NAVIGATE) */
  306.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXStreamSource*)this },
  307.         };
  308.     
  309.     HX_RESULT res = ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  310.     
  311.     // if successful, return immediately...
  312.     if (SUCCEEDED(res))
  313.     {
  314.         return res;
  315.     }
  316.     // ... otherwise proceed onward
  317.     
  318.     if (IsEqualIID(riid, IID_IHXBackChannel))
  319.     {
  320. if (m_pBackChannel)
  321. {
  322.     AddRef();
  323.     *ppvObj = (IHXBackChannel*)this;
  324.     return HXR_OK;
  325. }
  326. else
  327. {
  328.     *ppvObj = NULL;
  329.     return HXR_NOINTERFACE;
  330. }
  331.     }
  332.     else if (IsEqualIID(riid, IID_IHXASMSource))
  333.     {
  334. if (m_pASMSource)
  335. {
  336.     AddRef();
  337.     *ppvObj = (IHXASMSource*)this;
  338.     return HXR_OK;
  339. }
  340. else
  341. {
  342.     *ppvObj = NULL;
  343.     return HXR_NOINTERFACE;
  344. }
  345.     }
  346. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  347.     else if (IsEqualIID(riid, IID_IHXUpgradeCollection))
  348.     {
  349. if (!m_pUpgradeCollection)
  350. {
  351.     m_pUpgradeCollection = new HXUpgradeCollection;
  352.     m_pUpgradeCollection->AddRef();
  353. }
  354. return m_pUpgradeCollection->QueryInterface(riid, ppvObj);
  355.     }
  356. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  357.     else if (m_pRequest &&
  358. m_pRequest->QueryInterface(riid, ppvObj) == HXR_OK)
  359.     {
  360. return HXR_OK;
  361.     }
  362.     else if (m_pFileHeader &&
  363. m_pFileHeader->QueryInterface(riid, ppvObj) == HXR_OK)
  364.     {
  365. return HXR_OK;
  366.     }
  367.     *ppvObj = NULL;
  368.     return HXR_NOINTERFACE;
  369. }
  370. /////////////////////////////////////////////////////////////////////////
  371. // Method:
  372. // IUnknown::AddRef
  373. // Purpose:
  374. // Everyone usually implements this the same... feel free to use
  375. // this implementation.
  376. //
  377. STDMETHODIMP_(ULONG32) HXSource::AddRef()
  378. {
  379.     return InterlockedIncrement(&m_lRefCount);
  380. }
  381. /////////////////////////////////////////////////////////////////////////
  382. // Method:
  383. // IUnknown::Release
  384. // Purpose:
  385. // Everyone usually implements this the same... feel free to use
  386. // this implementation.
  387. //
  388. STDMETHODIMP_(ULONG32) HXSource::Release()
  389. {
  390.     if (InterlockedDecrement(&m_lRefCount) > 0)
  391.     {
  392. return m_lRefCount;
  393.     }
  394.     delete this;
  395.     return 0;
  396. }
  397. // *** IHXStreamSource methods ***
  398. /************************************************************************
  399.  * Method:
  400.  * IHXStreamSource::IsLive
  401.  * Purpose:
  402.  * Ask the source whether it is live
  403.  *
  404.  */
  405. STDMETHODIMP_ (BOOL) HXSource::IsLive(void)
  406. {
  407.     return mLiveStream;
  408. }
  409. /************************************************************************
  410.  * Method:
  411.  *     IHXStreamSource::GetPlayer
  412.  * Purpose:
  413.  *     Get the interface to the player object of which the source is
  414.  *     a part of.
  415.  *
  416.  */
  417. STDMETHODIMP HXSource::GetPlayer(IHXPlayer* &pPlayer)
  418. {
  419.     pPlayer = m_pPlayer;
  420.     if (pPlayer)
  421.     {
  422. pPlayer->AddRef();
  423.     }
  424.     return HXR_OK;
  425. }
  426. /************************************************************************
  427.  * Method:
  428.  *     IHXStreamSource::GetContext
  429.  * Purpose:
  430.  *     Get the interface to the context object of which the source is
  431.  *     a part of.
  432.  *
  433.  */
  434. STDMETHODIMP HXSource::GetContext(IUnknown* &pContext)
  435. {
  436.     pContext = ((IUnknown*)(IHXClientEngine*) m_pEngine);
  437.     if (pContext)
  438.     {
  439. pContext->AddRef();
  440.     }
  441.     return HXR_OK;
  442. }
  443. /************************************************************************
  444.  * Method:
  445.  *     IHXStreamSource::GetURL
  446.  * Purpose:
  447.  *     Get the URL for this source. NOTE: The returned string is
  448.  *     assumed to be valid for the life of the IHXStreamSource from which it
  449.  *     was returned.
  450.  *
  451.  */
  452. STDMETHODIMP_(const char*) HXSource::GetURL(void)
  453. {
  454.     const char* pURL = NULL;
  455.     /* 
  456.      * Make sure that the we have not been re-directed
  457.      * to a new URL.
  458.      */ 
  459.     if (m_pRequest && 
  460. m_pRequest->GetURL(pURL) == HXR_OK &&
  461. pURL)
  462.     {
  463. if (!m_pszURL ||
  464.     ::strcasecmp(pURL, m_pszURL) != 0)
  465. {
  466.     HX_VECTOR_DELETE(m_pszURL);
  467.     m_pszURL = new char[strlen(pURL) + 1];
  468.     strcpy(m_pszURL, pURL); /* Flawfinder: ignore */
  469. }
  470.     }
  471.     // append RAM mimeType as URL option to notify the
  472.     // caller(i.e. ViewSource)
  473.     if (m_bIsMeta)
  474.     {
  475. char* pszTemp = NULL;
  476. pszTemp = ::HXFindChar(m_pszURL, '?');
  477. if (pszTemp)
  478. {
  479. int lenTemp = strlen(m_pszURL) + strlen("&mimeType=") + strlen(RAM_MIMETYPE) + 1;
  480.     pszTemp = new char[lenTemp];
  481.     SafeSprintf(pszTemp, lenTemp, "%s%s%s", m_pszURL, "&mimeType=", RAM_MIMETYPE); /* Flawfinder: ignore */
  482. }
  483. else
  484. {
  485. int lenTemp = strlen(m_pszURL) + strlen("?mimeType=") + strlen(RAM_MIMETYPE) + 1;
  486.     pszTemp = new char[lenTemp];
  487.     SafeSprintf(pszTemp, lenTemp, "%s%s%s", m_pszURL, "?mimeType=", RAM_MIMETYPE); /* Flawfinder: ignore */
  488. }
  489. HX_VECTOR_DELETE(m_pszURL);
  490. m_pszURL = pszTemp;
  491.     }
  492.     return m_pszURL;
  493. }
  494. /************************************************************************
  495.  * Method:
  496.  *     IHXStreamSource::GetStreamCount
  497.  * Purpose:
  498.  *     Get the number of streams in this source
  499.  *
  500.  */
  501. STDMETHODIMP_(UINT16)
  502. HXSource::GetStreamCount()
  503. {
  504.     return m_HXStreamList.GetCount();
  505. }
  506. /************************************************************************
  507.  * Method:
  508.  *     IHXStreamSource::GetStream
  509.  * Purpose:
  510.  *     Get the stream with the given index.
  511.  * Note: 
  512.  *     Since stream numbers may not be zero based, stream index is not
  513.  *     equal to the stream number. Actual stream number may be determined 
  514.  *     from IHXStream::GetStreamNumber()
  515.  *
  516.  */
  517. STDMETHODIMP
  518. HXSource::GetStream
  519. (
  520.     UINT16 nIndex,
  521.     REF(IUnknown*) pUnknown
  522. )
  523. {
  524.     LISTPOSITION lPosition = m_HXStreamList.FindIndex((int) nIndex);
  525.     if (!lPosition)
  526.     {
  527. pUnknown = NULL;
  528. return HXR_INVALID_PARAMETER;
  529.     }
  530.     HXStream* pStream = (HXStream*) m_HXStreamList.GetAt(lPosition);
  531.     HX_ASSERT(pStream);
  532.     return pStream->QueryInterface(IID_IUnknown,(void**)&pUnknown);
  533. }
  534. // IHXPrivateStreamSource methods 
  535. STDMETHODIMP_(BOOL) HXSource::IsSaveAllowed()
  536. {
  537.     return mSaveAsAllowed;
  538. }
  539. /*
  540.  * IHXBackChannel method
  541.  */
  542. /************************************************************************
  543.  * Method:
  544.  *     IHXBackChannel::PacketReady
  545.  * Purpose:
  546.  *      A back channel packet sent from Renderer to FileFormat plugin.
  547.  */
  548. STDMETHODIMP
  549. HXSource::PacketReady(IHXPacket* pPacket)
  550. {
  551.     HX_ASSERT(m_pBackChannel);
  552.     if (m_pBackChannel)
  553.     {
  554. return m_pBackChannel->PacketReady(pPacket);
  555.     }
  556.     return HXR_FAIL;
  557. }
  558. /*
  559.  * IHXASMSource methods
  560.  */
  561. /************************************************************************
  562.  * Method:
  563.  *     IHXASMSource::Subscribe
  564.  * Purpose:
  565.  *      Called to inform a file format that a subscription has occurred,
  566.  *     to rule number uRuleNumber, for stream uStreamNumber.
  567.  */
  568. STDMETHODIMP
  569. HXSource::Subscribe(UINT16 uStreamNumber,
  570.      UINT16 uRuleNumber)
  571. {
  572.     HX_ASSERT(m_pASMSource);
  573.     if (m_pASMSource)
  574.     {
  575. return m_pASMSource->Subscribe(uStreamNumber, uRuleNumber);
  576.     }
  577.     return HXR_FAIL;
  578. }
  579. /************************************************************************
  580.  * Method:
  581.  *     IHXASMSource::Unsubscribe
  582.  * Purpose:
  583.  *      Called to inform a file format that a unsubscription has occurred,
  584.  *     to rule number uRuleNumber, for stream uStreamNumber.
  585.  */
  586. STDMETHODIMP
  587. HXSource::Unsubscribe(UINT16 uStreamNumber,
  588.        UINT16 uRuleNumber)
  589. {
  590.     HX_ASSERT(m_pASMSource);
  591.     if (m_pASMSource)
  592.     {
  593. return m_pASMSource->Unsubscribe(uStreamNumber, uRuleNumber);
  594.     }
  595.     return HXR_FAIL;
  596. }
  597. void
  598. HXSource::AddHXStream(HXStream* pStream)
  599. {
  600.     pStream->AddRef();
  601.     m_HXStreamList.AddTail(pStream);
  602.     UINT16 uStreamNumber = pStream->GetStreamNumber();
  603.     STREAM_INFO* pStreamInfo;
  604.     if (mStreamInfoTable->Lookup((LONG32) uStreamNumber, (void*& )pStreamInfo))
  605.     {
  606. pStreamInfo->m_pStream = pStream;
  607. pStreamInfo->m_pStream->AddRef();
  608. pStreamInfo->BufferingState().OnStream((IHXStream*)pStream);
  609.     }
  610. }
  611. HX_RESULT
  612. HXSource::CollectAudioStreams(CHXSimpleList*& pAudioStreamList)
  613. {
  614. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  615.     HX_RESULT     rc = HXR_OK;
  616.     UINT16     i = 0;
  617.     UINT16     uNumAudioStreams = 0;
  618.     CHXAudioPlayer* pAudioPlayer = NULL;
  619.     CHXAudioStream* pCHXAudioStream = NULL;
  620.     IHXValues*     pHeader = NULL;
  621.     pAudioStreamList = NULL;
  622.     if (!m_pPlayer)
  623.     {
  624. goto cleanup;
  625.     }
  626.     pAudioPlayer = m_pPlayer->GetAudioPlayer();
  627.     if (!pAudioPlayer)
  628.     {
  629. goto cleanup;
  630.     }
  631.     uNumAudioStreams = pAudioPlayer->GetAudioStreamCount();
  632.     for (i = 0; i < uNumAudioStreams; i++)
  633.     {
  634. pCHXAudioStream = pAudioPlayer->GetCHXAudioStream(i);
  635. pCHXAudioStream->AddRef();
  636. pHeader = ((IHXAudioStream*)pCHXAudioStream)->GetStreamInfo();
  637. if (pHeader &&
  638.     IsAudioStreamFromThisSource(pHeader))
  639. {
  640.     if (!pAudioStreamList)
  641.     {
  642. pAudioStreamList = new CHXSimpleList();
  643.     }
  644.     pAudioStreamList->AddTail(pCHXAudioStream);
  645. }
  646. else
  647. {
  648.     HX_RELEASE(pCHXAudioStream);
  649. }
  650. HX_RELEASE(pHeader);
  651.     }
  652. cleanup:
  653.     if (!pAudioStreamList)
  654.     {  
  655. rc = HXR_FAILED;
  656.     }
  657.     return rc;
  658. #else
  659.     return HXR_NOTIMPL;
  660. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  661. }
  662. void
  663. HXSource::RemoveAudioStreams(void)
  664. {    
  665. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  666.     CHXAudioPlayer* pAudioPlayer = NULL;
  667.     CHXSimpleList*  pAudioStreamList = NULL;
  668.     if (!m_pPlayer)
  669.     {
  670. goto cleanup;
  671.     }
  672.     pAudioPlayer = m_pPlayer->GetAudioPlayer();
  673.     if (!pAudioPlayer)
  674.     {
  675. goto cleanup;
  676.     }
  677.     pAudioPlayer->AddRef();
  678.     if (HXR_OK == CollectAudioStreams(pAudioStreamList) && pAudioStreamList)
  679.     {
  680. pAudioPlayer->ManageAudioStreams(pAudioStreamList, CHXAudioPlayer::STR_REMOVE);
  681. ReleaseAudioStreams(pAudioStreamList);
  682. HX_DELETE(pAudioStreamList);
  683.     }
  684.     HX_RELEASE(pAudioPlayer);
  685. cleanup:
  686. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  687.     return;
  688. }
  689. void
  690. HXSource::PauseAudioStreams(void)
  691. {
  692. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  693.     CHXAudioPlayer* pAudioPlayer = NULL;
  694.     CHXSimpleList*  pAudioStreamList = NULL;
  695.     if (!m_pPlayer)
  696.     {
  697. goto cleanup;
  698.     }
  699.     pAudioPlayer = m_pPlayer->GetAudioPlayer();
  700.     if (!pAudioPlayer)
  701.     {
  702. goto cleanup;
  703.     }
  704.     pAudioPlayer->AddRef();
  705.     if (HXR_OK == CollectAudioStreams(pAudioStreamList) && pAudioStreamList)
  706.     {
  707. pAudioPlayer->ManageAudioStreams(pAudioStreamList, CHXAudioPlayer::STR_PAUSE);
  708. ReleaseAudioStreams(pAudioStreamList);
  709. HX_DELETE(pAudioStreamList);
  710.     }
  711.     HX_RELEASE(pAudioPlayer);
  712. cleanup:
  713. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  714.     return;
  715. }
  716. void
  717. HXSource::ResumeAudioStreams(void)
  718. {
  719. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  720.     CHXAudioPlayer* pAudioPlayer = NULL;
  721.     CHXSimpleList*  pAudioStreamList = NULL;
  722.     if (!m_pPlayer)
  723.     {
  724. goto cleanup;
  725.     }
  726.     pAudioPlayer = m_pPlayer->GetAudioPlayer();
  727.     if (!pAudioPlayer)
  728.     {
  729. goto cleanup;
  730.     }
  731.     pAudioPlayer->AddRef();
  732.     if (HXR_OK == CollectAudioStreams(pAudioStreamList) && pAudioStreamList)
  733.     {
  734. pAudioPlayer->ManageAudioStreams(pAudioStreamList, CHXAudioPlayer::STR_RESUME);
  735. ReleaseAudioStreams(pAudioStreamList);
  736. HX_DELETE(pAudioStreamList);
  737.     }
  738.     HX_RELEASE(pAudioPlayer);
  739. cleanup:
  740. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  741.     return;
  742. }
  743. void
  744. HXSource::ReleaseAudioStreams(CHXSimpleList* pAudioStreamList)
  745. {
  746. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  747.     if (pAudioStreamList && !pAudioStreamList->IsEmpty())
  748.     {
  749. CHXSimpleList::Iterator lIter = pAudioStreamList->Begin();
  750. for (; lIter != pAudioStreamList->End(); ++lIter)
  751. {
  752.     CHXAudioStream* pAudioStream = (CHXAudioStream*) (*lIter);
  753.     HX_RELEASE(pAudioStream);
  754. }
  755.     }
  756. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  757.     return;
  758. }
  759. HX_RESULT HXSource::Init(HXPlayer * pPlayer, UINT32 unRegistryID)
  760. {
  761.     HX_RESULT theErr = HXR_OK;
  762.    
  763.     m_pPlayer = pPlayer;
  764.     if (m_pPlayer->QueryInterface(IID_IHXPreferences, (void **) &m_pPreferences) != HXR_OK)
  765.     {
  766. theErr = HXR_INVALID_PARAMETER; //HX_INVALID_INTERFACE;
  767.     }
  768.     m_pBufferManager = new CBufferManager(this);
  769.     if(!m_pBufferManager)
  770.     {
  771.         theErr = HXR_OUTOFMEMORY;
  772.     }
  773.     // create registry entries
  774.     if (HXR_OK != m_pPlayer->QueryInterface(IID_IHXRegistry, (void**)&m_pRegistry))
  775.     {
  776. m_pRegistry = NULL;
  777.     }
  778.     else
  779.     {
  780. m_ulRegistryID = unRegistryID;
  781.     }
  782.     if (!theErr &&
  783. m_pPlayer->QueryInterface(IID_IHXScheduler, (void **) &m_pScheduler) != HXR_OK)
  784.     {
  785. theErr = HXR_INVALID_PARAMETER; //HX_INVALID_INTERFACE;
  786.     }
  787.     IHXPreferences* pPref = NULL;
  788.     m_pPlayer->QueryInterface(IID_IHXPreferences, (void**)&pPref);
  789.     if (HXR_OK == ReadPrefINT32(pPref, "TurboPushdown", m_ulTurboPushDown))
  790.     {
  791. m_ulTurboPushDown = (m_ulTurboPushDown / 100) * 100;  // round to multiple of 100
  792.     }
  793.     HX_RELEASE(pPref);
  794.     m_pEngine = m_pPlayer->m_pEngine;
  795.     m_pEngine->AddRef();
  796.     return theErr;
  797. }
  798. HX_RESULT HXSource::SetupRegistry()
  799. {
  800.     HX_RESULT theErr = HXR_OK;
  801. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  802.     UINT32 ulRepeatedRegistryID = 0;
  803.     IHXBuffer* pRepeatRegName = NULL;
  804.     char        szSourceName[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
  805.     HX_ASSERT(m_pSourceInfo);    
  806.     if (m_pSourceInfo->m_bLeadingSource &&
  807. !m_pSourceInfo->m_pRepeatList)
  808.     {
  809. m_pStats = new SOURCE_STATS(m_pRegistry, m_ulRegistryID);
  810.     }
  811.     else if (m_pRegistry && 
  812.     HXR_OK == m_pRegistry->GetPropName(m_pPlayer->m_ulRepeatedRegistryID, pRepeatRegName))
  813.     {
  814. SafeSprintf(szSourceName, MAX_DISPLAY_NAME, "%s.%ld%ld%ld", 
  815. pRepeatRegName->GetBuffer(),
  816. m_pSourceInfo->m_uGroupID,
  817. m_pSourceInfo->m_uTrackID,
  818. (int)m_pSourceInfo->m_bLeadingSource);
  819.     
  820. ulRepeatedRegistryID = m_pRegistry->GetId(szSourceName);
  821. if (!ulRepeatedRegistryID)
  822. {
  823.     ulRepeatedRegistryID = m_pRegistry->AddComp(szSourceName);
  824. }
  825. m_pStatsManager = new StatsManager(m_pRegistry, m_ulRegistryID, ulRepeatedRegistryID);
  826. m_pStatsManager->AddRef();
  827. m_pStats = new SOURCE_STATS(m_pRegistry, ulRepeatedRegistryID);
  828.         if( !m_pStats )
  829.         {
  830.             theErr = HXR_OUTOFMEMORY;
  831.         }
  832.     }
  833.     else
  834.     {
  835. // why stats' creation failed??
  836. HX_ASSERT(FALSE);
  837.     }
  838.     HX_RELEASE(pRepeatRegName);
  839. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  840.     return theErr;
  841. }
  842. HX_RESULT HXSource::ReadPreferences(void)
  843. {
  844.     UINT32      un16Temp = 10;
  845.     ReadPrefINT32(m_pPreferences, "PerfectPlayTime", un16Temp); 
  846.     m_ulPerfectPlayTime = un16Temp;
  847.     ReadPrefINT32(m_pPreferences, "BufferedPlayTime", un16Temp);
  848.     m_ulBufferedPlayTime = un16Temp;
  849.     ReadPrefBOOL(m_pPreferences, "PerfPlayEntireClip", m_bPerfectPlayEntireClip); 
  850.     return HXR_OK;
  851. }
  852. HX_RESULT HXSource::DeleteStreamTable(void)
  853. {
  854.     HX_RESULT theErr = HXR_OK;
  855.     STREAM_INFO * sInfo = NULL;
  856.     for (CHXMapLongToObj::Iterator i = mStreamInfoTable->Begin();
  857.          i != mStreamInfoTable->End(); ++i) 
  858.     {    
  859. sInfo = (STREAM_INFO*) (*i);
  860. if (sInfo)
  861. {
  862.     HX_DELETE (sInfo);
  863. }
  864.     }
  865.     mStreamInfoTable->RemoveAll();
  866.     m_ulStreamIndex = 0;
  867.     m_uNumStreams = 0;
  868.     
  869.     return theErr;
  870. }
  871. IHXValues* HXSource::GetHeaderInfo(UINT16 stream_number)
  872. {
  873.     STREAM_INFO * pStreamInfo;
  874.     if (mStreamInfoTable->Lookup((LONG32) stream_number, (void*& )pStreamInfo))
  875.     {
  876. return pStreamInfo->m_pHeader;
  877.     }
  878.     else
  879.     {
  880. return NULL;
  881.     }
  882. }
  883. HX_RESULT
  884. HXSource::GetStreamHeaderInfo(UINT16 index, IHXValues*& hdr)
  885. {
  886.     HX_TRACE("HXSource::GetStreamHeaderInfo");
  887.     
  888.     // sanity check
  889.     if (index >= m_uNumStreams)
  890.     {
  891. return HXR_INVALID_PARAMETER; // HX_INVALID_INDEX;
  892.     }
  893.     
  894.     CHXMapLongToObj::Iterator i = mStreamInfoTable->Begin();
  895.     for (UINT16 j=0; j < index; j++)
  896.     {
  897. ++i;
  898.     }
  899.     STREAM_INFO* pStreamInfo = (STREAM_INFO*) *i;
  900.     hdr = pStreamInfo->m_pHeader;
  901.     if (hdr)
  902.     {
  903. hdr->AddRef();
  904.     }
  905.     return HXR_OK;
  906. }
  907. void HXSource::SetFlags(UINT16 flags)
  908. {
  909.     mFlags = flags;
  910.     if (mFlags & HX_PERFECT_PLAY_ENABLED)
  911.     {
  912. m_bPerfectPlayAllowed = TRUE;
  913.     }
  914.     else
  915.     {
  916. m_bPerfectPlayAllowed = FALSE;
  917.     }
  918.     if (mFlags & HX_SAVE_ENABLED)
  919.     {
  920. mSaveAsAllowed = TRUE;
  921.     }
  922.     else
  923.     {
  924. mSaveAsAllowed = FALSE;
  925.     }
  926. }
  927. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  928. HX_RESULT HXSource::CopyMetaDataToRegistry(IHXValues* pHeader)
  929. {
  930.     // get Request Object
  931.     char pszServerMetaData[256] = {0}; /* Flawfinder: ignore */
  932.     char pszMetaData[256] = {0}; /* Flawfinder: ignore */
  933.     IHXValues* pReqHeaders = NULL;
  934.     IHXRequest* pRequest = NULL;
  935.     IHXBuffer* pBuffer = NULL;
  936.     char szRegKeyName[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
  937.     char buff[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
  938.     char szSMDKey[256]; /* Flawfinder: ignore */
  939.     ULONG32 ulValue = 0;
  940.     IHXBuffer* pParentName = NULL;
  941.     UINT32 regid = 0;
  942.     const char szServerMetaData[] = {"ServerMetaData"};
  943.     if (HXR_OK == m_pRegistry->GetPropName(m_pStats->m_ulRegistryID, pParentName))
  944.     {
  945. SafeStrCpy(buff, (const char*) pParentName->GetBuffer(), MAX_DISPLAY_NAME);
  946. char* pDot = strrchr(buff, '.');
  947. if (pDot)
  948. {
  949.     *pDot = '';
  950. }
  951. SafeStrCpy(szSMDKey, buff, 256);
  952. if (HXR_OK == GetRequest(pRequest))
  953. {
  954.     // get request headers
  955.     if (HXR_OK == pRequest->GetRequestHeaders(pReqHeaders))
  956.     {
  957. // look for the meta data properties
  958. if (HXR_OK == pReqHeaders->GetPropertyCString("AcceptMetaInfo", pBuffer))
  959. {
  960.     SafeStrCpy(pszMetaData, (char*) pBuffer->GetBuffer(), 256);
  961.     HX_RELEASE(pBuffer);
  962.     // look for comma delimited entries
  963.     const char* pCharEntryStart = pszMetaData;
  964.     const char* pCharEntryEnd = pCharEntryStart;
  965.     while (pCharEntryEnd && *pCharEntryEnd)
  966.     {
  967. ++pCharEntryEnd;
  968. if (*pCharEntryEnd == ',' || !*pCharEntryEnd)
  969. {
  970.     // copy next prop request into buffer 
  971.     strncpy(buff, pCharEntryStart, (UINT32)pCharEntryEnd - (UINT32)pCharEntryStart); /* Flawfinder: ignore */
  972.     *(buff+(UINT32)pCharEntryEnd - (UINT32)pCharEntryStart) = '';
  973.     // see if this prop is in file header (it should be!)
  974.     if (HXR_OK == pHeader->GetPropertyCString(buff, pBuffer))
  975.     {
  976. // create new registry entry
  977. SafeSprintf(szRegKeyName, MAX_DISPLAY_NAME, "%s.%s", pParentName->GetBuffer(), buff);
  978. regid = m_pRegistry->GetId(szRegKeyName);
  979. if (!regid)
  980. {
  981.     m_pRegistry->AddStr(szRegKeyName, pBuffer);
  982. }
  983. else
  984. {
  985.     // set new value
  986.     m_pRegistry->SetStrByName(szRegKeyName, pBuffer);
  987. }
  988. HX_RELEASE(pBuffer);
  989.     }
  990.     else if (HXR_OK == pHeader->GetPropertyULONG32(buff, ulValue))
  991.     {
  992. // create new registry entry
  993. SafeSprintf(szRegKeyName, MAX_DISPLAY_NAME, "%s.%s", pParentName->GetBuffer(), buff);
  994. regid = m_pRegistry->GetId(szRegKeyName);
  995. if (!regid)
  996. {
  997.     m_pRegistry->AddInt(szRegKeyName, ulValue);
  998. }
  999. else
  1000. {
  1001.     // set new value
  1002.     m_pRegistry->SetIntByName(szRegKeyName, ulValue);
  1003. }
  1004.     }
  1005.     pCharEntryStart = pCharEntryEnd + 1;
  1006. }
  1007.     }
  1008. }
  1009. // look for the meta data properties
  1010. if (HXR_OK == pReqHeaders->GetPropertyCString("AcceptServerMetaData", pBuffer))
  1011. {
  1012.     SafeStrCpy(pszServerMetaData, (char*) pBuffer->GetBuffer(), 256);
  1013.     HX_RELEASE(pBuffer);
  1014.     // first make sure we have a composit key for "statistics.Player0.ServerMetaData"
  1015.     SafeSprintf(buff, MAX_DISPLAY_NAME, "%s.%s", szSMDKey, szServerMetaData);
  1016.     regid = m_pRegistry->GetId(buff);
  1017.     if (!regid)
  1018.     {
  1019. m_pRegistry->AddComp(buff);
  1020.     }
  1021.     SafeStrCpy(szSMDKey, buff, 256);
  1022.     // look for comma delimited entries
  1023.     const char* pCharEntryStart = pszServerMetaData;
  1024.     const char* pCharEntryEnd = pCharEntryStart;
  1025.     while (pCharEntryEnd && *pCharEntryEnd)
  1026.     {
  1027. ++pCharEntryEnd;
  1028. if (*pCharEntryEnd == ',' || !*pCharEntryEnd)
  1029. {
  1030.     // copy next prop request into buffer 
  1031.     strncpy(buff, pCharEntryStart, (UINT32)pCharEntryEnd - (UINT32)pCharEntryStart); /* Flawfinder: ignore */
  1032.     *(buff+(UINT32)pCharEntryEnd - (UINT32)pCharEntryStart) = '';
  1033.     // see if this prop is in file header (it should be!)
  1034.     if (HXR_OK == pHeader->GetPropertyCString(buff, pBuffer))
  1035.     {
  1036. // create new registry entry (if one does not exist)
  1037. SafeSprintf(szRegKeyName, MAX_DISPLAY_NAME, "%s.%s", szSMDKey, buff);
  1038. regid = m_pRegistry->GetId(szRegKeyName);
  1039. if (!regid)
  1040. {
  1041.     m_pRegistry->AddStr(szRegKeyName, pBuffer);
  1042. }
  1043. else
  1044. {
  1045.     // set new value
  1046.     m_pRegistry->SetStrByName(szRegKeyName, pBuffer);
  1047. }
  1048. HX_RELEASE(pBuffer);
  1049.     }
  1050.     else if (HXR_OK == pHeader->GetPropertyULONG32(buff, ulValue))
  1051.     {
  1052. // create new registry entry
  1053. SafeSprintf(szRegKeyName, MAX_DISPLAY_NAME, "%s.%s", szSMDKey, buff);
  1054. regid = m_pRegistry->GetId(szRegKeyName);
  1055. if (!regid)
  1056. {
  1057.     m_pRegistry->AddInt(szRegKeyName, ulValue);
  1058. }
  1059. else
  1060. {
  1061.     // set new value
  1062.     m_pRegistry->SetIntByName(szRegKeyName, ulValue);
  1063. }
  1064.     }
  1065.     pCharEntryStart = pCharEntryEnd + 1;
  1066. }
  1067.     }
  1068. }
  1069. HX_RELEASE(pReqHeaders);
  1070.     }
  1071.     HX_RELEASE(pRequest);
  1072. }
  1073. HX_RELEASE(pParentName);
  1074.     }
  1075.     return HXR_OK;
  1076. }
  1077. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  1078. HX_RESULT HXSource::SetPlayTimes(UINT32 ulStartTime, 
  1079.   UINT32 ulEndTime, 
  1080.   UINT32 ulDelay, 
  1081.   UINT32 ulDuration)
  1082. {
  1083.     m_ulStartTime     = ulStartTime;
  1084.     m_ulEndTime     = ulEndTime;
  1085.     /* We do not handle Delay field for now */
  1086.     m_ulDelay     = ulDelay;
  1087.     m_ulRestrictedDuration  = ulDuration;
  1088.     if (m_ulEndTime > 0)
  1089.     {
  1090. m_bCustomEndTime = TRUE;
  1091.     }
  1092.     else
  1093.     {
  1094.      m_bCustomEndTime = FALSE;
  1095.     }
  1096.     return HXR_OK;
  1097. }
  1098. HX_RESULT
  1099. HXSource::UpdatePlayTimes(IHXValues* pValues)
  1100. {
  1101.     HX_RESULT rc = HXR_OK;
  1102.     char szStart[] = "Start";
  1103.     char szEnd[] = "End";
  1104.     char szDelay[] = "Delay";
  1105.     char szDuration[] = "Duration";
  1106.     UINT32 ulStartTime = 0;
  1107.     UINT32 ulEndTime = 0;
  1108.     UINT32 ulDelay = 0;
  1109.     UINT32 ulRestrictedDuration = 0;
  1110.     pValues->GetPropertyULONG32(szStart, ulStartTime);
  1111.     pValues->GetPropertyULONG32(szEnd, ulEndTime);
  1112.     pValues->GetPropertyULONG32(szDelay, ulDelay);
  1113.     pValues->GetPropertyULONG32(szDuration, ulRestrictedDuration);
  1114.     if (ulStartTime != m_ulStartTime    ||
  1115. ulEndTime != m_ulEndTime     ||
  1116. ulDelay != m_ulDelay     ||
  1117. ulRestrictedDuration != m_ulRestrictedDuration)
  1118.     {
  1119. SetPlayTimes(ulStartTime, ulEndTime, ulDelay, ulRestrictedDuration);
  1120. rc = AdjustClipTime();
  1121.     }
  1122.     return rc;
  1123. }
  1124. ULONG32 
  1125. HXSource::GetPerfectPlayTime(void)
  1126. {
  1127.     ULONG32 ulCurrentPlayTime = m_pPlayer ? m_pPlayer->GetCurrentPlayTime() : 0;
  1128.     ULONG32 result       = m_bPerfectPlay ? m_ulPerfectPlayTime : m_ulBufferedPlayTime;
  1129.     if (m_ulDuration != 0)
  1130.     {
  1131. // mPlaybackLength is in Milliseconds, we want to calculate
  1132. // playback in seconds...
  1133. ULONG32 playbackTimeLeftInClip = 
  1134.     ((m_ulDuration > ulCurrentPlayTime ? m_ulDuration - ulCurrentPlayTime : 0) /1000)+1;
  1135. /* Perfect Play entire clip ONLY if user has chosen PerfectPlay specifically
  1136.  * If we internally go in buffered play mode, always use perfect play time
  1137.  * setting.
  1138.  */
  1139. if (m_bPerfectPlay)
  1140. {
  1141.     if (m_bPerfectPlayEntireClip)
  1142.     {
  1143. result = playbackTimeLeftInClip;
  1144.     }
  1145.     else
  1146.     {
  1147. result = min(m_ulPerfectPlayTime, playbackTimeLeftInClip);
  1148.     }
  1149. }
  1150. else // if (m_bBufferedPlay)
  1151. {
  1152.     result = min(m_ulBufferedPlayTime, playbackTimeLeftInClip);
  1153. }
  1154.     }
  1155.     
  1156.     // check if enough memory is available to handle the result
  1157.     if(result > 0)
  1158.     {
  1159. // get 50% of the available memory
  1160. ULONG32 maxMemAvail = GetAvailableMemory() / 2;
  1161. ULONG32 bytesPerSecond = m_ulAvgBandwidth/8;
  1162. ULONG32 maxTimeAvail = maxMemAvail/(bytesPerSecond > 0 ? bytesPerSecond : 1);
  1163. // if this is true then we can't buffer the entire clip
  1164. if (maxTimeAvail < result)
  1165. m_bCannotBufferEntireClip = (m_bPerfectPlayEntireClip) ? TRUE : FALSE;
  1166. else
  1167. m_bCannotBufferEntireClip = FALSE;
  1168. result = min(result,maxTimeAvail);
  1169.     }
  1170.     /* Value now returned in ms. */
  1171.     return 1000*(max(result, PERFECTPLAY_MIN_TIME));
  1172. }
  1173. STDMETHODIMP 
  1174. HXSource::ReportRebufferStatus(UINT16 uStreamNumber,
  1175.         UINT8 unNeeded, 
  1176.         UINT8 unAvailable) 
  1177. {
  1178.     STREAM_INFO* pStreamInfo = 0;
  1179. //    if (m_bDelayed ||
  1180. // (m_ulDelay > 0 && m_ulDelay > m_pPlayer->GetCurrentPlayTime()))
  1181.     if (m_bDelayed)
  1182.     {
  1183. return HXR_OK;
  1184.     }
  1185.     DEBUG_OUT(m_pPlayer, DOL_TRANSPORT, (s, "(%p)ReportRebufferStatus %lu %lu %lu", this, uStreamNumber, unNeeded, unAvailable));
  1186.     if (mStreamInfoTable->Lookup((LONG32) uStreamNumber, (void*& )pStreamInfo))
  1187.     {
  1188. pStreamInfo->m_unNeeded     = unNeeded;
  1189. pStreamInfo->m_unAvailable  = unAvailable;
  1190. if (unNeeded > unAvailable)
  1191. {
  1192. //     dfprintf("buff", "reportrebufferstatus: %lun", m_pPlayer->GetInternalCurrentPlayTime());     
  1193. //     g_bRahulLog = TRUE;
  1194.     if (m_bFastStart)
  1195.     {
  1196.                 DEBUG_OUT(m_pPlayer, DOL_TRANSPORT, (s, "(%p)ALMOST Turbo OFF ReportRebufferStatus", this));
  1197.                 //with surestream audio only clips, rarender may report buffering immediately after resume
  1198.                 if (m_bSureStreamClip)
  1199. {
  1200.     if (CALCULATE_ELAPSED_TICKS(m_ulTurboStartActiveTime, HX_GET_TICKCOUNT()) > 1000)
  1201.     {
  1202. LeaveFastStart(TP_OFF_BY_REBUFFER);
  1203. DEBUG_OUT(m_pPlayer, DOL_TRANSPORT, (s, "(%p)Turbo OFF ReportRebufferStatus", this));
  1204.     }
  1205. }
  1206. else
  1207. {
  1208.                     LeaveFastStart(TP_OFF_BY_REBUFFER);
  1209.                     DEBUG_OUT(m_pPlayer, DOL_TRANSPORT, (s, "(%p)Turbo OFF ReportRebufferStatus", this));
  1210. }
  1211.     }
  1212.     // log rebuffer action
  1213.     LogInformation("BUFBEG", NULL);
  1214.     
  1215.     DoRebuffer();
  1216.   }
  1217. else
  1218. {
  1219.     m_bRebufferingRequired = IsRebufferRequired();
  1220.     if (!m_bRebufferingRequired)
  1221.     {
  1222. // log rebuffer action
  1223. LogInformation("BUFEND", NULL);
  1224.     }
  1225. }
  1226.         return HXR_OK;
  1227.     }
  1228.     return HXR_UNEXPECTED;
  1229. }
  1230. STDMETHODIMP 
  1231. HXSource::SetGranularity
  1232. (
  1233.     UINT16 uStreamNumber,
  1234.     ULONG32 ulGranularity
  1235. {
  1236.     STREAM_INFO* pStreamInfo = 0;
  1237.     if (mStreamInfoTable->Lookup((LONG32) uStreamNumber, (void*& )pStreamInfo))
  1238.     {
  1239. m_pPlayer->SetGranularity(this, uStreamNumber, ulGranularity);
  1240. return HXR_OK;
  1241.     }
  1242.     else
  1243.     {
  1244. return HXR_OK;
  1245.     }
  1246.     return HXR_UNEXPECTED;
  1247. }
  1248. BOOL
  1249. HXSource::TryResume(void)
  1250. {
  1251.     BOOL    bResume = FALSE;
  1252.     // resume the persistent source ASAP
  1253.     if (m_pSourceInfo && m_pSourceInfo->m_bIsPersistentSource)
  1254.     {
  1255.         m_bDelayed = FALSE;
  1256.         bResume = TRUE;
  1257.     }
  1258.     else if (m_bPaused && m_bDelayed && m_pPlayer &&
  1259.              m_pPlayer->CanBeStarted(this, m_pSourceInfo, m_bPartOfNextGroup))
  1260.     {
  1261.         UINT32 ulCurrentTime = m_pPlayer->GetInternalCurrentPlayTime();
  1262.         UINT32 ulStartTime = 0;
  1263.         if (m_ulDelay > m_ulPreRollInMs + NETWORK_FUDGE_FACTOR)
  1264.         {
  1265.             ulStartTime = m_ulDelay - (m_ulPreRollInMs + NETWORK_FUDGE_FACTOR);
  1266.         }
  1267.         if (ulCurrentTime >= ulStartTime)
  1268.         {
  1269.             m_bDelayed = FALSE;
  1270.             bResume = TRUE;
  1271.         }
  1272.         if (!m_bIsPreBufferingStarted)
  1273.         {
  1274.             m_bIsPreBufferingStarted = TRUE;
  1275.             bResume = TRUE;
  1276.         }
  1277.     }
  1278.     else if (m_bPrefetch)
  1279.     {
  1280.         bResume = TRUE;
  1281.     }
  1282.     if (bResume && CanBeResumed())
  1283.     {
  1284.         if (m_pSourceInfo)
  1285.         {
  1286.             m_pSourceInfo->Register();
  1287.         }
  1288.         m_bResumePending = TRUE;
  1289.     }
  1290.     return bResume;
  1291. }
  1292. BOOL
  1293. HXSource::IsAnyAudioStream(void)
  1294. {
  1295.     IHXAudioPlayer* pAudioPlayer = NULL;
  1296.     BOOL bAtLeastOneAudioStream = FALSE;
  1297.     if (!m_pPlayer)
  1298.     {
  1299. return FALSE;
  1300.     }
  1301.     m_pPlayer->QueryInterface(IID_IHXAudioPlayer, (void **) &pAudioPlayer);
  1302.     UINT16 uNumAudioStreams = pAudioPlayer->GetAudioStreamCount();
  1303.     for (UINT16 i = 0; i < uNumAudioStreams && !bAtLeastOneAudioStream; i++)
  1304.     {
  1305. IHXAudioStream* pAudioStream = pAudioPlayer->GetAudioStream(i);
  1306. IHXValues* pHeader = pAudioStream->GetStreamInfo();
  1307. pAudioStream->Release();
  1308. if (!pHeader)
  1309. {
  1310.     continue;
  1311. }
  1312. if (IsAudioStreamFromThisSource(pHeader))
  1313. {
  1314.     bAtLeastOneAudioStream = TRUE;
  1315.     pHeader->Release();
  1316.     break;
  1317. }
  1318. pHeader->Release();
  1319.     }
  1320.     if (!bAtLeastOneAudioStream)
  1321.     {
  1322.         IHXValues* pHeader = NULL;
  1323.         int nStreamCnt = GetNumStreams();
  1324.         ULONG32     ulIsAudioStream = FALSE;
  1325.         for (int i=0; i<nStreamCnt && !bAtLeastOneAudioStream; i++)
  1326.         {
  1327.             GetStreamHeaderInfo(i, pHeader);
  1328.             pHeader->GetPropertyULONG32("IsAudioStream", ulIsAudioStream);
  1329.             if (ulIsAudioStream)
  1330.             {
  1331.                 bAtLeastOneAudioStream = TRUE;
  1332.             }
  1333.     HX_RELEASE(pHeader);
  1334.         }
  1335.     }
  1336.     pAudioPlayer->Release();
  1337.     return bAtLeastOneAudioStream;
  1338. }
  1339. void
  1340. HXSource::EventReady(CHXEvent* pEvent)
  1341. {
  1342.     if (m_pPlayer)
  1343.     {
  1344. m_pPlayer->EventReady(this, pEvent);
  1345.     }
  1346. }
  1347. BOOL 
  1348. HXSource::IsAudioStreamFromThisSource(IHXValues* pAudioHeader)
  1349. {
  1350.     BOOL bFound = FALSE;
  1351.     CHXMapLongToObj::Iterator ndxStreamIterator = mStreamInfoTable->Begin();
  1352.     for (; ndxStreamIterator != mStreamInfoTable->End(); ++ndxStreamIterator) 
  1353.     {
  1354. STREAM_INFO* pStreamInfo = (STREAM_INFO*) (*ndxStreamIterator);
  1355. if (pStreamInfo->m_pHeader == pAudioHeader)
  1356. {
  1357.     bFound = TRUE;
  1358.     break;
  1359. }
  1360.     }
  1361.     return bFound;
  1362. }
  1363. ULONG32
  1364. HXSource::GetAvailableMemory()
  1365. {
  1366.     ULONG32 memAvail = 1000000;
  1367. #if   defined (__MWERKS__)
  1368. //  XXX Hack! We can't call any of the Memory Manager calls at interrupt time so we will have 
  1369. //  to change this to ask our interrupt safe memory allocator how much memory is free
  1370.     memAvail = 1000000;
  1371. #elif defined(_WINCE) && !defined(_WIN32_WCE_EMULATION)
  1372.     STORE_INFORMATION stInfo;
  1373.     GetStoreInformation(&stInfo);
  1374.     memAvail = stInfo.dwFreeSize;
  1375. #elif (_WIN32)
  1376.     MEMORYSTATUS status;
  1377.     status.dwLength = sizeof(MEMORYSTATUS);
  1378.     GlobalMemoryStatus(&status);
  1379.     memAvail = status.dwAvailPageFile;
  1380. #elif defined( _WINDOWS)
  1381.     memAvail = GetFreeSpace(0);
  1382. #elif defined (_UNIX)
  1383.     // XXXX Need to get this to compile.
  1384.     memAvail = 1000000;
  1385. #endif
  1386.     return memAvail;
  1387. }
  1388. void
  1389. HXSource::ReportError(HX_RESULT theErr)
  1390. {
  1391.     if (m_pPlayer)
  1392.     {
  1393. m_pPlayer->ReportError(this, theErr);
  1394.     }
  1395. }
  1396. HX_RESULT
  1397. HXSource::AdjustClipTime(void)
  1398. {
  1399.     HX_RESULT theErr = HXR_OK;
  1400.     UINT32  ulOriginalDuration = m_ulDuration;        
  1401.     UINT32  ulTrackEndTime = 0;
  1402.     CHXMapLongToObj::Iterator i;
  1403.     BOOL    bCustomEndTimeSet = FALSE;
  1404.     if (m_bPartOfPrefetchGroup)
  1405.     {
  1406. if (m_ulDelay)
  1407. {
  1408.     m_ulPrefetchDelay = m_ulDelay;
  1409.     m_bDelayed = TRUE;
  1410.     AdjustClipBandwidthStats(FALSE);
  1411.     DoPause();
  1412. }
  1413. m_ulEndTime = 0;
  1414. m_bCustomEndTime = FALSE;
  1415. goto cleanup;
  1416.     }
  1417.     /* For a live stream, the only qualifiers that make sense
  1418.      * are Duration and Delay. All other qualifiers should be made 0
  1419.      */
  1420.     if (mLiveStream)
  1421.     {
  1422. m_ulStartTime = 0;
  1423. if (!m_bRestrictedLiveStream)
  1424. {
  1425.     m_ulEndTime = 0;
  1426. }
  1427.     }
  1428.     for (i = mStreamInfoTable->Begin(); i != mStreamInfoTable->End(); ++i) 
  1429.     {    
  1430. STREAM_INFO* pStreamInfo = (STREAM_INFO*) (*i);
  1431. ulTrackEndTime = 0;
  1432. HX_RESULT hrTemp = pStreamInfo->m_pHeader->GetPropertyULONG32("EndTime", ulTrackEndTime);
  1433. if (HXR_OK == hrTemp && !m_bCustomEndTime)
  1434. {
  1435.     if (m_ulEndTime < ulTrackEndTime)
  1436.     {
  1437. m_ulEndTime = ulTrackEndTime;
  1438.     }
  1439.     pStreamInfo->m_bCustomEndTime = TRUE;
  1440. }
  1441. else if (m_bCustomEndTime)
  1442. {
  1443.     ulTrackEndTime = m_ulEndTime;
  1444.     pStreamInfo->m_bCustomEndTime = TRUE;
  1445. }
  1446. if (ulTrackEndTime > 0 && !mLiveStream)
  1447. {
  1448.     pStreamInfo->m_pHeader->SetPropertyULONG32("TrackEndTime",
  1449. ulTrackEndTime);
  1450.     bCustomEndTimeSet = TRUE;
  1451. }
  1452.     }
  1453.     
  1454.     // if max. duration is set on this source
  1455.     if (m_pSourceInfo && 
  1456. m_pSourceInfo->m_ulMaxDuration)
  1457.     {
  1458. if (m_ulRestrictedDuration)
  1459. {     
  1460.     if (m_ulRestrictedDuration > m_pSourceInfo->m_ulMaxDuration)
  1461.     {
  1462. m_ulRestrictedDuration = m_pSourceInfo->m_ulMaxDuration;
  1463.     }
  1464. }
  1465. else if (m_ulDuration)
  1466. {
  1467.     if (m_ulDuration > m_pSourceInfo->m_ulMaxDuration)
  1468.     {
  1469. m_ulRestrictedDuration = m_pSourceInfo->m_ulMaxDuration;
  1470.     }
  1471. }
  1472.     }
  1473.     // By default, we always set the end time to be the duration of the clip,
  1474.     // but do not set end time if it was manually specified.
  1475.     if (!bCustomEndTimeSet && !mLiveStream)
  1476.     {
  1477. m_ulEndTime = m_ulDuration;
  1478.     }
  1479.     /* Check if there is any end time */
  1480.     if ((m_ulEndTime < m_ulDuration) || m_bRestrictedLiveStream)
  1481.     {
  1482. m_ulDuration = m_ulEndTime;
  1483.     }
  1484.     
  1485.     /* Is "Delay" specified too? */
  1486.     if (m_ulDelay > 0) 
  1487.     {
  1488. /* Increase duration of this clip */
  1489. m_ulDuration += m_ulDelay;
  1490. UINT32 ulStartTime = 0;
  1491. if (m_ulDelay > m_ulPreRollInMs + NETWORK_FUDGE_FACTOR)
  1492. {
  1493.     ulStartTime = m_ulDelay - (m_ulPreRollInMs + NETWORK_FUDGE_FACTOR);
  1494. }
  1495. // no need to pause delayed persistent component since Pause() will be called
  1496. // on actual tracks' AdjustClipTime() if necessary
  1497. if (m_pSourceInfo && !m_pSourceInfo->m_bIsPersistentSource)
  1498. {
  1499.     m_bDelayed = TRUE;
  1500.     AdjustClipBandwidthStats(FALSE);
  1501.     DoPause();
  1502. }
  1503.     }
  1504.     if (m_ulStartTime > 0) /* reduce duration by start time amount */
  1505.     {
  1506.      if (m_ulDuration > m_ulStartTime)
  1507.      {
  1508.     m_ulDuration -= m_ulStartTime;
  1509. }
  1510. else
  1511. {
  1512.     /* This is bad case. We consider it invalid */
  1513.     m_ulDuration = 0;
  1514. }
  1515.     }
  1516.     /* We now allow to increase the default duration of the clip */
  1517.     if (m_ulRestrictedDuration > 0)
  1518.     {
  1519. m_ulDuration = m_ulRestrictedDuration + m_ulDelay;
  1520. if (mLiveStream && !m_bRestrictedLiveStream)
  1521. {
  1522.     m_bRestrictedLiveStream = TRUE;
  1523.     m_ulEndTime = m_ulRestrictedDuration + m_ulStartTime;
  1524. }
  1525. if (m_ulEndTime > m_ulRestrictedDuration + m_ulStartTime)
  1526. {
  1527.     m_ulEndTime = m_ulRestrictedDuration + m_ulStartTime;
  1528. }
  1529.     }
  1530.     // orig duration is active duration for this source -- time for which
  1531.     // this source lasts.
  1532.     if (m_ulDuration > m_ulDelay)
  1533.     {
  1534. m_ulOriginalDuration = m_ulDuration - m_ulDelay;
  1535.     }
  1536.     else
  1537.     {
  1538. m_ulOriginalDuration = 0;
  1539.     }
  1540.     if (m_pURL     &&
  1541. rtspProtocol == m_pURL->GetProtocol()     &&
  1542. m_llLastExpectedPacketTime != m_ulEndTime   &&
  1543. !m_bFirstResume)
  1544.     {
  1545. m_bRTSPRuleFlagWorkAround = TRUE;
  1546.     }
  1547.     /* If we receive a packet after this stream, we consider the stream to be done */
  1548.     m_llLastExpectedPacketTime  = CAST_TO_INT64 m_ulEndTime;
  1549.     // Seek to the starting position only if the source
  1550.     // has not been resumed yet
  1551.     if (m_ulStartTime > 0 && m_bFirstResume) 
  1552.     {
  1553. /* We will add m_ulStartTime in DoSeek() call*/
  1554.      theErr = DoSeek(0);
  1555.     }
  1556.     /* Update stream durations if required */
  1557.     for (i = mStreamInfoTable->Begin(); i != mStreamInfoTable->End(); ++i) 
  1558.     {    
  1559. STREAM_INFO* pStreamInfo = (STREAM_INFO*) (*i);
  1560. if (m_ulStartTime > 0)
  1561. {
  1562.     pStreamInfo->m_pHeader->SetPropertyULONG32("TrackStartTime",
  1563.     m_ulStartTime);
  1564. }
  1565. if (m_ulEndTime > 0 && 
  1566.     !mLiveStream    &&
  1567.     HXR_OK != pStreamInfo->m_pHeader->GetPropertyULONG32("TrackEndTime",
  1568.   ulTrackEndTime))
  1569. {
  1570.     pStreamInfo->m_pHeader->SetPropertyULONG32("TrackEndTime",
  1571. m_ulEndTime);
  1572. }
  1573. if (ulOriginalDuration != m_ulDuration)
  1574. {
  1575.     pStreamInfo->m_ulDuration = m_ulDuration;
  1576.     pStreamInfo->m_pHeader->SetPropertyULONG32("Duration", 
  1577. pStreamInfo->m_ulDuration);
  1578. }
  1579. if (m_ulDelay > 0)
  1580. {
  1581.     pStreamInfo->m_pHeader->SetPropertyULONG32("Delay", m_ulDelay);
  1582. }
  1583.     }
  1584. //{FILE* f1 = ::fopen("d:\temp\url.txt", "a+"); ::fprintf(f1, "%p %s %lu %lun", this, m_pszURL, m_ulDelay, m_ulDuration);::fclose(f1);}
  1585. cleanup:
  1586.     m_bClipTimeAdjusted = TRUE;
  1587.     return theErr;
  1588. }
  1589. void
  1590. HXSource::GenerateFakeLostPacket(CHXEvent*& theEvent)
  1591. {
  1592.     IHXPacket* pPacket = theEvent->GetPacket();
  1593.     CHXPacket* pLostPacket = new CHXPacket;
  1594.     pLostPacket->AddRef();
  1595.     pLostPacket->Set(0, 0, pPacket->GetStreamNumber(), 0, 0);
  1596.     pLostPacket->SetAsLost();
  1597.     /* Create a new event with lost packet */
  1598.     CHXEvent* pEvent = new CHXEvent(pLostPacket);
  1599.     pEvent->SetTimeStartPos(theEvent->GetTimeStartPos());
  1600.     pEvent->SetTimeOffset(theEvent->GetTimeOffset());
  1601.     pEvent->SetPreSeekEvent(theEvent->IsPreSeekEvent());
  1602.     pLostPacket->Release();
  1603.     delete theEvent;
  1604.     theEvent = pEvent;
  1605. }
  1606. char*
  1607. HXSource::GetAltURL(BOOL& bDefault)
  1608. {
  1609. #if defined(HELIX_FEATURE_ALT_URL)
  1610.     char*   pAltURL = NULL;
  1611.     if (!m_pURL || m_bInitialized)
  1612.     {
  1613. goto cleanup;
  1614.     }
  1615.     pAltURL = m_pURL->GetAltURL(bDefault);
  1616. cleanup:
  1617.     return pAltURL;
  1618. #else
  1619.     return NULL;
  1620. #endif /* HELIX_FEATURE_ALT_URL */
  1621. }
  1622. HX_RESULT
  1623. HXSource::SetRequest(const CHXURL* pURL, BOOL bAltURL)
  1624. {
  1625.     HX_RESULT hr = HXR_OK;
  1626.     IHXValues* pValues = NULL;
  1627.     IHXValues* pValuesInRequest = NULL;
  1628.     IHXGroup* pGroup = NULL;
  1629.     IHXGroup2* pGroup2 = NULL;
  1630.     IHXGroupManager* pGroupManager = NULL;
  1631.     HX_RELEASE(m_pRequest);
  1632.     if (m_pPlayer)
  1633.     {
  1634. m_pPlayer->GetActiveRequest(m_pRequest);
  1635. if (m_pRequest)
  1636. {
  1637.     m_pPlayer->ResetActiveRequest();
  1638. }
  1639.     }
  1640. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  1641.     if (m_pPlayer && m_pSourceInfo)
  1642.     {
  1643. if (HXR_OK == m_pPlayer->QueryInterface(IID_IHXGroupManager, (void**)&pGroupManager))
  1644. {
  1645.     if (HXR_OK == pGroupManager->GetGroup(m_pSourceInfo->m_uGroupID, pGroup))
  1646.     {
  1647. if (HXR_OK == pGroup->QueryInterface(IID_IHXGroup2, (void**)&pGroup2))
  1648. {
  1649.     pGroup2->GetTrack2(m_pSourceInfo->m_uTrackID, pValues, pValuesInRequest);
  1650.     UINT32 ulValue = 0;
  1651.     char   szDuration[128] = {0}; /* Flawfinder: ignore */
  1652.     IHXBuffer* pBuffer = NULL;
  1653.     if (pValues && HXR_OK == pValues->GetPropertyULONG32("Duration", ulValue))
  1654.     {
  1655. if (!pValuesInRequest)
  1656. {
  1657.     pValuesInRequest = new CHXHeader();
  1658.     if( pValuesInRequest )
  1659.     {
  1660.         pValuesInRequest->AddRef();
  1661.     }
  1662.     else
  1663.     {
  1664.         hr = HXR_OUTOFMEMORY;
  1665.     }
  1666. }
  1667. if (pValuesInRequest)
  1668. {
  1669.     SafeSprintf (szDuration, 128, "%lu", ulValue); /* Flawfinder: ignore */
  1670.     pBuffer = new CHXBuffer();
  1671.     pBuffer->AddRef();
  1672.          pBuffer->Set((UCHAR*)szDuration, strlen(szDuration) + 1);
  1673.     pValuesInRequest->SetPropertyCString("Duration", pBuffer);
  1674.     HX_RELEASE(pBuffer);
  1675. }
  1676.     }
  1677. }
  1678. HX_RELEASE(pGroup2);
  1679.     }
  1680.     HX_RELEASE(pGroup);
  1681. }
  1682. HX_RELEASE(pGroupManager);
  1683.     }
  1684. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  1685.     IHXRegistry* pRegistry = NULL;   
  1686.     m_pEngine->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
  1687.     hr = ::SetRequest(pURL->GetEscapedURL(), bAltURL, m_pPreferences, pRegistry, pValuesInRequest, m_pRequest);
  1688.     HX_RELEASE(pValues);
  1689.     HX_RELEASE(pValuesInRequest);
  1690.     HX_RELEASE(pRegistry);
  1691. #if defined(HELIX_FEATURE_RECORDCONTROL)
  1692.     if(hr == HXR_OK && pURL->GetProtocol() != fileProtocol)
  1693.     {
  1694. if(!m_pRecordControl)
  1695. {
  1696.     m_pRecordControl = new HXRecordControl((IHXPlayer*)m_pPlayer, (IHXStreamSource*)this);
  1697.     if(m_pRecordControl)
  1698.     {
  1699. m_pRecordControl->AddRef();
  1700. if(m_pRecordControl->IsValid())
  1701.                     m_bPlayFromRecordControl = m_pRecordControl->CanGetPackets();
  1702.                 else
  1703.     HX_RELEASE(m_pRecordControl);
  1704.     }
  1705. }
  1706. if(m_pRecordControl)
  1707. {
  1708.     m_pRecordControl->SetSource((IHXStreamSource*)this);
  1709. }
  1710.     }
  1711. #endif /* HELIX_FEATURE_RECORDCONTROL */
  1712.     return hr;
  1713. }
  1714. void
  1715. HXSource::UpdateDuration(UINT32 ulDuration)
  1716. {
  1717.     CHXSimpleList* pRepeatList = m_pSourceInfo->GetRepeatList();
  1718.     // ulDuration excludes the delay time
  1719.     if (pRepeatList && 
  1720. ulDuration >= (m_ulDuration - m_ulDelay))
  1721.     {
  1722. m_pSourceInfo->m_ulTotalTrackDuration = ulDuration + m_ulDelay;
  1723. if (m_pSourceInfo->m_pPeerSourceInfo)
  1724. {
  1725.     m_pSourceInfo->m_pPeerSourceInfo->m_ulTotalTrackDuration = m_pSourceInfo->m_ulTotalTrackDuration;
  1726. }
  1727.     }
  1728.     else
  1729.     {
  1730. m_ulOriginalDuration = m_ulRestrictedDuration = ulDuration;
  1731. AdjustClipTime();
  1732. m_pSourceInfo->UpdateDuration(m_ulDuration);
  1733.     }
  1734. }
  1735. void
  1736. HXSource::UpdateDelay(UINT32 ulDelay)
  1737. {
  1738.     m_ulDelay = ulDelay;
  1739.     AdjustClipTime();
  1740.     m_pSourceInfo->UpdateDelay(m_ulDelay);
  1741. }
  1742. void
  1743. HXSource::InitialBufferingDone(void)
  1744. {
  1745.     m_bInitialBuffering = FALSE;
  1746.     // resume if we satisfy the initial preroll AND we have issued
  1747.     // rebuffer
  1748.     // note: IsRebufferRequired() should return FALSE!!
  1749.     if (m_bRebufferingRequired)
  1750.     {
  1751. m_bRebufferingRequired = IsRebufferRequired();
  1752. HX_ASSERT(!m_bRebufferingRequired);
  1753.     }
  1754.     return;
  1755. }
  1756. void
  1757. HXSource::DoRebuffer(void)
  1758. {
  1759.     m_bRebufferingRequired  = TRUE;
  1760.     if (m_pPlayer)
  1761.     {
  1762. m_pPlayer->InternalPause();     
  1763.         ReBuffer();
  1764.     }
  1765.     return;
  1766. }
  1767. BOOL
  1768. HXSource::IsRebufferRequired(void)
  1769. {
  1770.     BOOL     bResult = FALSE;
  1771.     STREAM_INFO*    pStreamInfo = NULL;
  1772.     // Check if all streams are doing OK
  1773.     for (CHXMapLongToObj::Iterator ndxStrm = mStreamInfoTable->Begin();
  1774.  ndxStrm != mStreamInfoTable->End(); ++ndxStrm) 
  1775.     {    
  1776. pStreamInfo = (STREAM_INFO*) (*ndxStrm);
  1777. if (pStreamInfo->m_unNeeded > pStreamInfo->m_unAvailable)
  1778. {
  1779.     bResult = TRUE;
  1780.     break;
  1781. }
  1782.     }
  1783.     return bResult;
  1784. }
  1785. BOOL
  1786. HXSource::IsRebufferDone(void)
  1787. {
  1788.     BOOL    bResult = TRUE;
  1789.     if (m_pSourceInfo)
  1790.     {
  1791. bResult = m_pSourceInfo->IsRebufferDone();
  1792.     }
  1793.     return bResult;
  1794. }
  1795. void
  1796. HXSource::ScheduleProcessCallback()
  1797. {
  1798.     if (m_pSourceInfo)
  1799.     {
  1800.         m_pSourceInfo->ScheduleProcessCallback();
  1801.     }
  1802. }
  1803. #if defined(HELIX_FEATURE_HYPER_NAVIGATE)
  1804. /************************************************************************
  1805.  * Method:
  1806.  *     IHXHyperNavigate::GoToURL
  1807.  * Purpose:
  1808.  *     Acts as a proxy for actual hypernavigate interface.
  1809.  *     Is used to convert any relative URLs to absolute URLs
  1810.  */
  1811. STDMETHODIMP 
  1812. HXSource::GoToURL(const char* pURL, const char* pTarget)
  1813. {
  1814.     return Execute(pURL, pTarget, NULL, NULL, NULL);
  1815. }
  1816. /************************************************************************
  1817.  * Method:
  1818.  *     IHXHyperNavigate2::Execute
  1819.  * Purpose:
  1820.  *     
  1821.  * Parameters:
  1822.  *      pURL:     URL (absolute or relative)
  1823.  *     pTargetInstance:
  1824.  *     pTargetApplication: 
  1825.  *     pTargetRegion:
  1826.  *     pParams:
  1827.  */
  1828. STDMETHODIMP 
  1829. HXSource::Execute(const char* pURL,
  1830.    const char* pTargetInstance,
  1831.    const char* pTargetApplication,
  1832.    const char* pTargetRegion,
  1833.    IHXValues* pParams)
  1834. {
  1835.     HX_RESULT theErr = HXR_OK;
  1836.     CHXString newURL = pURL;
  1837. //    pURL = "rogers.rt";
  1838. //    if (pTargetInstance && 
  1839. // stricmp(pTargetInstance, "_player") == 0 &&
  1840.     if (ShouldConvert(pTargetInstance) && 
  1841. pURL  &&
  1842. strnicmp(pURL, URL_COMMAND, sizeof(URL_COMMAND) - 1) != 0 )
  1843.     {
  1844. CHXURL urlObj(pURL);
  1845. IHXValues* pHeader = urlObj.GetProperties();
  1846. IHXBuffer* pBuffer = NULL;
  1847. if(pHeader && 
  1848.    m_pszURL &&
  1849.    HXR_OK != pHeader->GetPropertyBuffer(PROPERTY_SCHEME, pBuffer))
  1850. {
  1851.     // relative URL
  1852.     // if it starts with '/', make it relative to the root of 
  1853.     // the URL prefix
  1854.     CHXString urlPrefix, urlRoot;
  1855.     char* pURLFragment = NULL;
  1856.     theErr = CHXURL::GeneratePrefixRootFragment(m_pszURL, urlPrefix, urlRoot, pURLFragment);
  1857.     HX_VECTOR_DELETE(pURLFragment);
  1858.     if (!theErr)
  1859.     {
  1860. if(*pURL == '/')
  1861. {
  1862.     newURL = urlRoot + pURL;
  1863. }
  1864. else
  1865. {
  1866.     newURL = urlPrefix + pURL;
  1867. }
  1868.     }
  1869. }
  1870. HX_RELEASE(pBuffer);
  1871. HX_RELEASE(pHeader);
  1872.     }
  1873.     
  1874.     AddRef();
  1875.     HX_ASSERT(m_pPlayer && m_pPlayer->m_pHyperNavigate);
  1876.     if (m_pPlayer && m_pPlayer->m_pHyperNavigate)
  1877.     {
  1878. theErr = m_pPlayer->m_pHyperNavigate->ExecuteWithContext(newURL, 
  1879. pTargetInstance, pTargetApplication, pTargetRegion, 
  1880. pParams, (IUnknown*) (IHXStreamSource*) this);
  1881.     }
  1882.     Release();
  1883.     return theErr;
  1884. }
  1885. #endif /* defined(HELIX_FEATURE_HYPER_NAVIGATE) */
  1886. STDMETHODIMP
  1887. HXSource::GetTotalBuffering(UINT16  uStreamNumber,
  1888.     REF(INT64)  llLowestTimestamp, 
  1889.     REF(INT64)  llHighestTimestamp,
  1890.     REF(UINT32) ulNumBytes,
  1891.     REF(BOOL)   bDone)
  1892. {
  1893.     HX_RESULT res = HXR_NO_DATA;
  1894.     
  1895.     llLowestTimestamp = 0;
  1896.     llHighestTimestamp = 0;
  1897.     ulNumBytes = 0;
  1898.     bDone = FALSE;
  1899.     STREAM_INFO* pStreamInfo;
  1900.     if (mStreamInfoTable->Lookup((LONG32) uStreamNumber, (void*& )pStreamInfo))
  1901.     {
  1902. HXBufferingState& bufState = pStreamInfo->BufferingState();
  1903. BOOL   bUseTransportStats = FALSE;
  1904. INT64  llTransportLowTS = 0;
  1905. INT64  llTransportHighTS = 0;
  1906. UINT32 ulTransportBytes = 0;
  1907. BOOL   bTransportDone = FALSE;
  1908. if (!IsLocalSource() &&
  1909.     (HXR_OK == GetCurrentBuffering(uStreamNumber,
  1910.    llTransportLowTS,
  1911.    llTransportHighTS,
  1912.    ulTransportBytes,
  1913.    bTransportDone)))
  1914. {
  1915.     bufState.UpdateTransportStats(llTransportLowTS,
  1916.   llTransportHighTS,
  1917.   ulTransportBytes,
  1918.   bTransportDone);
  1919.     bUseTransportStats = TRUE;
  1920.     // Update bDone with what the transport says.
  1921.     bDone = bTransportDone;
  1922. }
  1923. res = bufState.GetBufferingStats(llLowestTimestamp,
  1924.  llHighestTimestamp,
  1925.  ulNumBytes,
  1926.  bUseTransportStats);
  1927.     }
  1928.     return res;
  1929. }
  1930. /* 
  1931.  * All relative URLs are converted to absolute URLs unless the 
  1932.  * original request (ram/smil) passed in OpenRequest/OpenURL()
  1933.  * is a mem: URL AND the target is not _player.
  1934.  *
  1935.  * This fixes relative URLs being hurled to the browser using events
  1936.  * come from the same location as the .ram file. (Broadcase usage case)
  1937.  * PR 31352
  1938.  *
  1939.  * This also fixes content on CD-ROMs where relative URLs being hurled 
  1940.  * to the browser using events come from the same location as 
  1941.  * the .rm file in which they are merged. 
  1942.  * PR 23489
  1943.  */
  1944. BOOL HXSource::ShouldConvert(const char* pTargetInstance)
  1945. {
  1946.     if (pTargetInstance && 
  1947. stricmp(pTargetInstance, "_player") == 0)
  1948.     {
  1949. return TRUE;
  1950.     }
  1951.     
  1952.     const char* pPlayerURL = NULL;
  1953.     IHXRequest* pPlayerRequest = NULL;
  1954.     if (m_pPlayer)
  1955.     {
  1956. m_pPlayer->GetRequest(pPlayerRequest);
  1957. if (pPlayerRequest)
  1958. {
  1959.     pPlayerRequest->GetURL(pPlayerURL);
  1960. }
  1961.     }
  1962.     HX_RELEASE(pPlayerRequest);
  1963.     if (pPlayerURL && ::strncasecmp(pPlayerURL, "mem:", 4) == 0)
  1964.     {
  1965. return FALSE;
  1966.     }
  1967.     return TRUE;
  1968. }
  1969. void
  1970. HXSource::MergeUpgradeRequest(BOOL bAddDefault /*= FALSE*/, char* pUpgradeString /* = NULL*/)
  1971. {
  1972. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  1973.     if (m_pPlayer && 
  1974. bAddDefault && 
  1975. (!m_pUpgradeCollection || m_pUpgradeCollection->GetCount() == 0))
  1976.     {
  1977. if (!m_pUpgradeCollection)
  1978. {
  1979.     m_pUpgradeCollection = new HXUpgradeCollection;
  1980. }
  1981. if (!pUpgradeString)
  1982. {
  1983.     pUpgradeString = "Missing Component";
  1984. }
  1985. IHXBuffer* pPluginID = (IHXBuffer*) new CHXBuffer;
  1986. pPluginID->AddRef();
  1987. pPluginID->Set((const UINT8*)pUpgradeString, strlen(pUpgradeString) + 1);
  1988. m_pUpgradeCollection->Add(eUT_Required, pPluginID, 0, 0);
  1989. pPluginID->Release();
  1990.     }
  1991.     if (m_pPlayer && m_pUpgradeCollection && m_pUpgradeCollection->GetCount() > 0)
  1992.     {
  1993. UINT32 ulCount = m_pUpgradeCollection->GetCount();
  1994. IHXUpgradeCollection* pPlayerUpgrade;
  1995. m_pPlayer->QueryInterface(IID_IHXUpgradeCollection, (void**) &pPlayerUpgrade);
  1996. for (UINT32 i = 0; i < ulCount; i++)
  1997. {
  1998.     HXUpgradeType upgradeType;
  1999.     IHXBuffer* pPluginId = (IHXBuffer*) new CHXBuffer;
  2000.     UINT32 majorVersion;
  2001.     UINT32 minorVersion;
  2002.     pPluginId->AddRef(); 
  2003.     // GetAt is a non-COM like API. It expects pPluginID to be allocated by the user
  2004.     // and does not perform an addref either!
  2005.     m_pUpgradeCollection->GetAt(i, upgradeType, pPluginId, majorVersion, minorVersion);
  2006.     pPlayerUpgrade->Add(upgradeType, pPluginId, majorVersion, minorVersion);
  2007.     pPluginId->Release();
  2008. }
  2009. pPlayerUpgrade->Release();
  2010. m_pUpgradeCollection->RemoveAll();
  2011.     }
  2012. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  2013. }
  2014. void
  2015. HXSource::ClearUpgradeRequest()
  2016. {
  2017. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  2018.     if (m_pUpgradeCollection)
  2019.     {
  2020. m_pUpgradeCollection->RemoveAll();
  2021.     }
  2022. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  2023. }
  2024. void
  2025. HXSource::EnterPrefetch(PrefetchType prefetchType, UINT32 ulPrefetchValue)
  2026. {
  2027.     m_bPrefetch = TRUE;
  2028.     m_prefetchType = prefetchType;
  2029.     m_ulPrefetchValue = ulPrefetchValue;
  2030.     return;
  2031. }
  2032. void
  2033. HXSource::LeavePrefetch(void)
  2034. {
  2035.     m_bPrefetch = FALSE;
  2036.     // send prefetch notification so that SMIL
  2037.     // renderer can resolve the duration on this prefetch track
  2038.     if (m_pSourceInfo)
  2039.     {
  2040. m_pPlayer->PrefetchTrackDone(m_pSourceInfo->m_uGroupID, 
  2041.           m_pSourceInfo->m_uTrackID, 
  2042.      HXR_OK);
  2043.     }
  2044.     return;
  2045. }
  2046. void
  2047. HXSource::SetSoundLevel(UINT16 uSoundLevel, BOOL bReflushAudioDevice)
  2048. {
  2049. #if defined(HELIX_FEATURE_SMIL_SOUNDLEVEL)
  2050.     CHXAudioPlayer* pAudioPlayer = NULL;
  2051.     CHXAudioStream* pCHXAudioStream = NULL;
  2052.     CHXSimpleList*  pAudioStreamList = NULL;
  2053.     if (!m_pPlayer)
  2054.     {
  2055. goto cleanup;
  2056.     }
  2057.     pAudioPlayer = m_pPlayer->GetAudioPlayer();
  2058.     if (!pAudioPlayer)
  2059.     {
  2060. goto cleanup;
  2061.     }
  2062.     pAudioPlayer->AddRef();
  2063.     if (HXR_OK == CollectAudioStreams(pAudioStreamList) && pAudioStreamList)
  2064.     {
  2065. pAudioPlayer->SetSoundLevel(pAudioStreamList, uSoundLevel, bReflushAudioDevice);
  2066. ReleaseAudioStreams(pAudioStreamList);
  2067. HX_DELETE(pAudioStreamList);
  2068.     }
  2069.     HX_RELEASE(pAudioPlayer);
  2070. cleanup:
  2071. #endif /* HELIX_FEATURE_SMIL_SOUNDLEVEL */
  2072.     return;
  2073. }
  2074. void
  2075. HXSource::SetAudioDeviceReflushHint(void)
  2076. {
  2077. #if defined(HELIX_FEATURE_SOUNDLEVEL)
  2078.     CHXAudioPlayer* pAudioPlayer = NULL;
  2079.     CHXSimpleList*  pAudioStreamList = NULL;
  2080.     if (!m_pPlayer)
  2081.     {
  2082. goto cleanup;
  2083.     }
  2084.     pAudioPlayer = m_pPlayer->GetAudioPlayer();
  2085.     if (!pAudioPlayer)
  2086.     {
  2087. goto cleanup;
  2088.     }
  2089.     pAudioPlayer->AddRef();
  2090.     if (HXR_OK == CollectAudioStreams(pAudioStreamList) && pAudioStreamList)
  2091.     {
  2092. pAudioPlayer->ManageAudioStreams(pAudioStreamList, CHXAudioPlayer::STR_SETHINT);
  2093. ReleaseAudioStreams(pAudioStreamList);
  2094. HX_DELETE(pAudioStreamList);
  2095.     }
  2096.     HX_RELEASE(pAudioPlayer);
  2097. cleanup:
  2098. #endif /* HELIX_FEATURE_SOUNDLEVEL */
  2099.     return;
  2100. }
  2101. void
  2102. HXSource::LeaveFastStart(TurboPlayOffReason leftReason)
  2103. {
  2104.     m_turboPlayStats.tpOffReason = leftReason;
  2105.     m_bFastStart = FALSE;
  2106. }
  2107. void
  2108. HXSource::DeleteAllEvents()
  2109. {
  2110.     if (m_PacketBufferList.GetCount() > 0)
  2111.     {
  2112. LISTPOSITION pos = m_PacketBufferList.GetHeadPosition();
  2113. while (pos != NULL)
  2114. {
  2115.     CHXEvent* pTempEvent  = (CHXEvent*) m_PacketBufferList.GetNext(pos);
  2116.     delete pTempEvent;
  2117. }
  2118. m_PacketBufferList.RemoveAll();
  2119.     }
  2120. }
  2121. void
  2122. HXSource::SetMinimumPreroll(ULONG32 ulMinimumAudioPreroll, ULONG32 ulMinimumStartingPreroll)
  2123. {
  2124.     UINT32 ulTotalMinimumPreroll = 0;
  2125.     if (m_pPlayer)
  2126.     {
  2127. // get the user-set minimum preroll
  2128. m_pPlayer->GetMinimumPreroll(ulTotalMinimumPreroll);
  2129.     }
  2130.     if (IsAnyAudioStream())
  2131.     {
  2132. m_ulPreRollInMs += ulMinimumAudioPreroll;
  2133.     }
  2134.     if (m_ulPreRollInMs < ulTotalMinimumPreroll)
  2135.     {
  2136. m_ulPreRollInMs = ulTotalMinimumPreroll;
  2137.     }
  2138.     DEBUG_OUT(m_pPlayer, DOL_TRANSPORT, (s, "(%p)Preroll: %lu MinPreroll %lu MinAudioPreroll %lu", this, m_ulPreRollInMs, ulTotalMinimumPreroll, ulMinimumStartingPreroll));
  2139.     m_pBufferManager->SetMinimumPreroll(IsLocalSource() | m_bPerfectPlay,
  2140. ulTotalMinimumPreroll,
  2141. ulMinimumStartingPreroll);
  2142. }
  2143. HX_RESULT
  2144. HXSource::SendHeaderToRecordControl(BOOL bFileHeader, IHXValues* pHeader)
  2145. {
  2146. #if defined(HELIX_FEATURE_RECORDCONTROL)
  2147.     HX_RESULT nResult = HXR_OK;
  2148.     if(m_pRecordControl && pHeader)
  2149.     {
  2150. if(bFileHeader)
  2151.     nResult = m_pRecordControl->OnFileHeader(pHeader);
  2152. else
  2153.     nResult = m_pRecordControl->OnStreamHeader(pHeader);
  2154. if(nResult != HXR_OK)
  2155. {
  2156.     m_bPlayFromRecordControl = FALSE;
  2157.     if(nResult != HXR_RECORD)
  2158. HX_RELEASE(m_pRecordControl);
  2159. }
  2160.     }
  2161.     return nResult;
  2162. #else
  2163.     return HXR_NOTIMPL;
  2164. #endif /* HELIX_FEATURE_RECORDCONTROL */
  2165. }
  2166. void
  2167. HXSource::ProcessFileHeader(void)
  2168. {
  2169.     UINT32      bNonSeekAble = 0;
  2170.     IHXBuffer*  pTitle = NULL;
  2171.     IHXBuffer*  pAuthor = NULL;
  2172.     IHXBuffer*  pCopyright = NULL;
  2173.     IHXBuffer*  pAbstract = NULL;
  2174.     IHXBuffer*  pDescription = NULL;
  2175.     IHXBuffer*  pKeywords = NULL;
  2176.     IHXValues*  pValues = NULL;
  2177.     if (m_pURL)
  2178.     {
  2179. pValues = m_pURL->GetOptions();
  2180.     }
  2181.     // retrieve the TAC from the URL
  2182.     if (pValues)
  2183.     {
  2184. pValues->GetPropertyBuffer("Title", pTitle);
  2185.         pValues->GetPropertyBuffer("Author", pAuthor);
  2186.         pValues->GetPropertyBuffer("Copyright", pCopyright);
  2187.         pValues->GetPropertyBuffer("Abstract", pAbstract);
  2188.         pValues->GetPropertyBuffer("Description", pDescription);
  2189.         pValues->GetPropertyBuffer("Keywords", pKeywords);
  2190. //#define LOSS_HACK
  2191. #ifdef LOSS_HACK
  2192. UINT32 ulLoss = 0;
  2193. if (HXR_OK == pValues->GetPropertyULONG32("Loss", ulLoss))
  2194. {
  2195.     m_ulLossHack = ulLoss;
  2196.     /* Initialize random number generator */
  2197.     ::srand((unsigned int) HX_GET_TICKCOUNT());
  2198. }
  2199. #endif /*LOSS_HACK*/
  2200.     }
  2201.     if (m_pFileHeader)
  2202.     {
  2203.         if (!pTitle)     m_pFileHeader->GetPropertyBuffer("Title", pTitle);
  2204.         if (!pAuthor)     m_pFileHeader->GetPropertyBuffer("Author", pAuthor);
  2205.         if (!pCopyright)    m_pFileHeader->GetPropertyBuffer("Copyright", pCopyright);
  2206.         if (!pDescription)  m_pFileHeader->GetPropertyCString("Description", pDescription);
  2207.         if (!pAbstract)     m_pFileHeader->GetPropertyCString("Abstract", pAbstract);
  2208.         if (!pKeywords)     m_pFileHeader->GetPropertyCString("Keywords", pKeywords);
  2209.         m_pFileHeader->GetPropertyULONG32("NonSeekable", bNonSeekAble);
  2210. m_bNonSeekable = bNonSeekAble ? TRUE : FALSE;
  2211.         
  2212.         m_pFileHeader->GetPropertyULONG32("StreamCount",m_ulStreamHeadersExpected);
  2213.             
  2214.         HX_ASSERT(mStreamInfoTable->IsEmpty() == TRUE);
  2215.         if (mStreamInfoTable->IsEmpty() && m_ulStreamHeadersExpected > 0 &&
  2216.             m_ulStreamHeadersExpected < mStreamInfoTable->GetHashTableSize())
  2217.         {
  2218.             mStreamInfoTable->InitHashTable(m_ulStreamHeadersExpected);
  2219.         }
  2220.     }
  2221. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  2222.     if (m_pStats)
  2223.     {
  2224.         if (pTitle && m_pStats->m_pTitle)
  2225.         {
  2226.     m_pStats->m_pTitle->SetStr((char*)(pTitle->GetBuffer()));
  2227.         }
  2228.         if (pAuthor && m_pStats->m_pAuthor)
  2229.         {
  2230.     m_pStats->m_pAuthor->SetStr((char*)(pAuthor->GetBuffer()));
  2231.         }
  2232.         if (pCopyright && m_pStats->m_pCopyright)
  2233.         {
  2234.     m_pStats->m_pCopyright->SetStr((char*)(pCopyright->GetBuffer()));
  2235.         }
  2236.         if (pAbstract && m_pStats->m_pAbstract)
  2237.         {
  2238.     m_pStats->m_pAbstract->SetStr((char*)(pAbstract->GetBuffer()));
  2239.         }
  2240.     
  2241.         if (pDescription && m_pStats->m_pDescription)
  2242.         {
  2243.             m_pStats->m_pDescription->SetStr((char*)(pDescription->GetBuffer()));
  2244.         }
  2245.         if (pKeywords && m_pStats->m_pKeywords)
  2246.         {
  2247.     m_pStats->m_pKeywords->SetStr((char*)(pKeywords->GetBuffer()));
  2248.         }
  2249.     }
  2250.     CopyMetaDataToRegistry(m_pFileHeader);
  2251. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  2252.     m_bReceivedHeader = TRUE;
  2253.     HX_RELEASE(pTitle);
  2254.     HX_RELEASE(pAuthor);
  2255.     HX_RELEASE(pCopyright);
  2256.     HX_RELEASE(pAbstract);
  2257.     HX_RELEASE(pDescription);
  2258.     HX_RELEASE(pKeywords);
  2259.     HX_RELEASE(pValues);
  2260.     return;
  2261. }
  2262. static BOOL GetHeaderBOOL(IHXValues* pHeader, const char* pKey)
  2263. {
  2264.     BOOL bRet = FALSE;
  2265.     ULONG32 ulTemp = 0;
  2266.     if ((HXR_OK == pHeader->GetPropertyULONG32(pKey, ulTemp)) && ulTemp)
  2267.     {
  2268. bRet = TRUE;
  2269.     }
  2270.     return bRet;
  2271. }
  2272. HX_RESULT
  2273. HXSource::ProcessStreamHeaders(IHXValues* pHeader, STREAM_INFO*& pStreamInfo)
  2274. {
  2275.     HX_RESULT       rc = HXR_OK;
  2276.     UINT32          ulStreamNumber = 0;
  2277.     UINT32          ulAvgBitRate = 0;
  2278.     UINT32          ulAvgPacketSize = 0;
  2279.     UINT32          ulPreroll = 0;
  2280.     ULONG32         ulPredata = 0;
  2281.     UINT32          ulDuration = 0;
  2282.     UINT32          ulTemp = 0;
  2283.     void*           lTmp = NULL;
  2284.     pStreamInfo = NULL;
  2285.     if (!pHeader)
  2286.     {
  2287.         rc = HX_INVALID_HEADER;
  2288.         goto cleanup;
  2289.     }
  2290.     // Use file header for default duration
  2291.     if (m_pFileHeader)
  2292.     {
  2293.         m_pFileHeader->GetPropertyULONG32("Duration", ulDuration);
  2294.         if (!m_ulDuration && ulDuration)
  2295.         {
  2296.             m_ulDuration = ulDuration;
  2297.             ulDuration = 0;
  2298.         }
  2299.     }
  2300.     pHeader->GetPropertyULONG32("StreamNumber",     ulStreamNumber);
  2301.     pHeader->GetPropertyULONG32("AvgBitRate",     ulAvgBitRate);
  2302.     pHeader->GetPropertyULONG32("AvgPacketSize",    ulAvgPacketSize);
  2303.     pHeader->GetPropertyULONG32("Preroll",     ulPreroll);
  2304.     pHeader->GetPropertyULONG32("Predata",          ulPredata);
  2305.     pHeader->GetPropertyULONG32("Duration",     ulDuration);
  2306.     if (mStreamInfoTable->Lookup((LONG32) ulStreamNumber, (void *&) lTmp))
  2307.     {
  2308. // a header with this stream number already exists..
  2309.         rc = HX_INVALID_HEADER;
  2310.         goto cleanup;
  2311.     }
  2312.     // max preroll
  2313.     if (m_ulPreRollInMs < ulPreroll)
  2314.     {
  2315. m_ulPreRollInMs = ulPreroll;
  2316.     }
  2317.     m_ulAvgBandwidth   += ulAvgBitRate;
  2318.     // max duration...
  2319.     if (m_ulDuration < ulDuration)
  2320.     {
  2321. m_ulDuration = ulDuration;
  2322.     }
  2323.     pStreamInfo = new STREAM_INFO;
  2324.     if (!pStreamInfo)
  2325.     {
  2326. rc = HXR_OUTOFMEMORY;
  2327.         goto cleanup;
  2328.     }
  2329.     pStreamInfo->m_pHeader                  = pHeader;
  2330.     pStreamInfo->m_pHeader->AddRef();
  2331.     pStreamInfo->m_bCustomEndTime           = FALSE;
  2332.     pStreamInfo->m_bSrcStreamDone           = FALSE;
  2333.     pStreamInfo->m_bSrcStreamFillingDone    = FALSE;
  2334.     pStreamInfo->m_bPacketRequested         = FALSE;
  2335.     
  2336.     pStreamInfo->m_uStreamNumber = (UINT16) ulStreamNumber;
  2337.     pStreamInfo->m_ulDuration = ulDuration;
  2338.     pStreamInfo->BufferingState().OnStreamHeader(
  2339. ulPreroll,
  2340. ulPredata,
  2341. GetHeaderBOOL(pHeader, "PreDataAtStart"),
  2342. GetHeaderBOOL(pHeader, "PreDataAfterSeek"),
  2343. GetHeaderBOOL(pHeader, "PrerollAtStart"),
  2344. GetHeaderBOOL(pHeader, "PrerollAfterSeek"),
  2345. ulAvgBitRate);
  2346.     mStreamInfoTable->SetAt(ulStreamNumber, (void *) pStreamInfo);
  2347. cleanup:
  2348.     return rc;
  2349. }
  2350. HX_RESULT HXSource::OnTimeSync(ULONG32 ulCurrentTime)
  2351. {
  2352.     HX_RESULT res = HXR_OK;
  2353.     for (CHXMapLongToObj::Iterator i = mStreamInfoTable->Begin();
  2354.          i != mStreamInfoTable->End(); ++i) 
  2355.     {    
  2356. STREAM_INFO* pStreamInfo = (STREAM_INFO*) (*i);
  2357. pStreamInfo->BufferingState().OnTimeSync(ulCurrentTime);
  2358.     }
  2359.     return res;
  2360. }