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

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.       
  36. #include "hxcom.h"
  37. #include "hlxclib/stdio.h"
  38. #include "hxassert.h"
  39. #include "hxslist.h"
  40. #include "hxcomm.h"
  41. #include "hxengin.h"
  42. #include "ihxpckts.h"
  43. #include "hxplugn.h"
  44. #include "hxfiles.h"
  45. #include "hxformt.h"
  46. #include "hxmeta.h"
  47. #include "hxcore.h"
  48. #include "hxprefs.h"
  49. #include "hxausvc.h"
  50. #include "hxgroup.h"
  51. #include "hxsmbw.h"
  52. #include "hxstring.h"
  53. #include "chxeven.h"
  54. #include "chxelst.h"
  55. #include "strminfo.h"
  56. #include "hxflsrc.h"
  57. //#include "raevents.h"
  58. #include "hxtick.h"
  59. #include "hxplay.h"
  60. #include "hxtypes.h"
  61. #include "timeval.h"
  62. #include "pq.h"
  63. #include "hxsched.h"
  64. #include "hxstat.h"
  65. #include "dbcs.h"
  66. #include "hxcleng.h"
  67. #include "hxauth.h"
  68. #include "hxrquest.h"
  69. #include "hxstrutl.h"
  70. #include "hxupgrd.h"
  71. #include "srcinfo.h"
  72. #include "plghand2.h"
  73. #include "rmfftype.h"
  74. #include "hxxfile.h"
  75. #include "upgrdcol.h"
  76. #include "uri_schemes.h"
  77. #include "stream_desc_hlpr.h"
  78. #include "hxheap.h"
  79. #ifdef _DEBUG
  80. #undef HX_THIS_FILE
  81. static const char HX_THIS_FILE[] = __FILE__;
  82. #endif
  83. #define FILEREAD_SIZE   4096
  84. HXFileSource::HXFileSource() 
  85.     : m_lRefCount(0)
  86.     , m_pFSObject(NULL)
  87.     , m_pFFObject(NULL)
  88.     , m_pRAMFFObject(NULL)
  89.     , m_pFileResponse(NULL)
  90.     , m_pFileFormatEnumerator(NULL)
  91.     , m_pCurrentFileFormatUnk(NULL)
  92.     , m_bCurrentFileFormatUnkInUse(FALSE)
  93.     , m_pFileObject(NULL)
  94.     , m_pRequestHandler(NULL)
  95.     , m_pMimeType(NULL)
  96.     , m_pExtension(NULL)
  97.     , m_pMimeFinderResponse(NULL)
  98.     , m_ulLastBufferingReturned(0)
  99.     , m_ulMaxPreRoll(0)
  100.     , m_uNumStreamsToBeFilled(0)
  101.     , m_bInFillMode(FALSE)
  102.     , m_llFillEndTime(0)
  103.     , m_llLastFillEndTime (0)
  104.     , m_bInitialPacket(TRUE)
  105.     , m_bFastStartInProgress(FALSE)
  106.     , m_bAddDefaultUpgrade(FALSE)
  107.     , m_pDefaultUpgradeString(NULL)
  108. #if defined(HELIX_FEATURE_ASM)
  109.     , m_pSimulatedSourceBandwidth(NULL)
  110. #endif /* HELIX_FEATURE_ASM */
  111.     , m_bValidateMetaDone(FALSE)
  112.     , m_pFileRecognizer(NULL)
  113.     , m_pFileReader(NULL)
  114. {
  115.     m_bAltURL = FALSE;
  116.     m_bPerfectPlay = TRUE;
  117. }
  118. HXFileSource::~HXFileSource()
  119. {
  120.     DoCleanup();
  121. }
  122. /////////////////////////////////////////////////////////////////////////
  123. // Method:
  124. // IUnknown::QueryInterface
  125. // Purpose:
  126. // Implement this to export the interfaces supported by your 
  127. // object.
  128. //
  129. STDMETHODIMP 
  130. HXFileSource::QueryInterface(REFIID riid, void** ppvObj)
  131. {
  132.     if (HXSource::QueryInterface(riid, ppvObj) == HXR_OK)
  133.     {
  134. return HXR_OK;
  135.     }
  136.     else if (IsEqualIID(riid, IID_IHXRegistryID))
  137.     {
  138. AddRef();
  139. *ppvObj = (IHXRegistryID*)this;
  140. return HXR_OK;
  141.     }
  142.     else if (IsEqualIID(riid, IID_IHXFormatResponse))
  143.     {
  144. AddRef();
  145. *ppvObj = (IHXFormatResponse*)this;
  146. return HXR_OK;
  147.     }
  148.     // XXX HP
  149.     // we assume the FF object doesn't QI from its m_pContext within
  150.     // its ::QueryInterface(), otherwise we are in trouble!! - indefinite
  151.     // loop
  152.     // This is for IHXBackChannel, IHXASMSource
  153.     else if (m_pFFObject && m_pFFObject->QueryInterface(riid, ppvObj) == HXR_OK)
  154.     {
  155. return HXR_OK;
  156.     }
  157. #if defined(HELIX_FEATURE_ASM)
  158.     else if (m_pSimulatedSourceBandwidth &&
  159.      m_pSimulatedSourceBandwidth->QueryInterface(riid, ppvObj) == HXR_OK)
  160.     {
  161. return HXR_OK;
  162.     }
  163. #endif /* HELIX_FEATURE_ASM */
  164.     else if (m_pPlayer &&
  165.      m_pPlayer->QueryInterface(riid, ppvObj) == HXR_OK)
  166.     {
  167. return HXR_OK;
  168.     }
  169.     // we don't have m_pPlayer during AutoConfig    
  170.     else if (m_pEngine &&
  171.      m_pEngine->QueryInterface(riid, ppvObj) == HXR_OK)
  172.     {
  173. return HXR_OK;
  174.     }
  175.     *ppvObj = NULL;
  176.     return HXR_NOINTERFACE;
  177. }
  178. /////////////////////////////////////////////////////////////////////////
  179. // Method:
  180. // IUnknown::AddRef
  181. // Purpose:
  182. // Everyone usually implements this the same... feel free to use
  183. // this implementation.
  184. //
  185. STDMETHODIMP_(ULONG32) 
  186. HXFileSource::AddRef()
  187. {
  188.     return InterlockedIncrement(&m_lRefCount);
  189. }
  190. /////////////////////////////////////////////////////////////////////////
  191. // Method:
  192. // IUnknown::Release
  193. // Purpose:
  194. // Everyone usually implements this the same... feel free to use
  195. // this implementation.
  196. //
  197. STDMETHODIMP_(ULONG32) 
  198. HXFileSource::Release()
  199. {
  200.     if (InterlockedDecrement(&m_lRefCount) > 0)
  201.     {
  202. return m_lRefCount;
  203.     }
  204.     delete this;
  205.     return 0;
  206. }
  207. void
  208. HXFileSource::ReSetup()
  209. {
  210.     m_ulLastBufferingReturned = 0;;
  211.     m_ulFirstPacketTime = 0;
  212.     m_llFillEndTime = 0;
  213.     m_llLastFillEndTime = 0;
  214.     m_ulMaxPreRoll = 0;
  215.     m_uNumStreamsToBeFilled = 0;    
  216.     m_bInitialized = FALSE;
  217.     m_bInFillMode = FALSE;
  218.     m_bInitialPacket = TRUE;
  219.     m_bFastStartInProgress = FALSE;
  220.     m_ulStreamHeadersExpected = 0;
  221.     if (m_pURL)
  222.     {
  223.         CHXURL* pURL = new CHXURL(*m_pURL);
  224. #if defined(HELIX_FEATURE_SMIL_REPEAT)
  225. if (m_pSourceInfo)
  226. {
  227.     CHXSimpleList* pRepeatList = m_pSourceInfo->m_bLeadingSource?m_pSourceInfo->m_pRepeatList:
  228.  m_pSourceInfo->m_pPeerSourceInfo->m_pRepeatList;
  229.     if (pRepeatList)
  230.     {
  231. RepeatInfo* pRepeatInfo = (RepeatInfo*)pRepeatList->GetAt(m_pSourceInfo->m_curPosition);
  232. m_ulDelay = m_pSourceInfo->m_ulRepeatDelayTimeOffset + pRepeatInfo->ulDelay;
  233. if (m_pSourceInfo->m_bRepeatIndefinite &&
  234.     m_pSourceInfo->m_ulMaxDuration &&
  235.     m_ulDelay + pRepeatInfo->ulDuration > m_ulOriginalDelay + m_pSourceInfo->m_ulMaxDuration)
  236. {
  237.     m_ulRestrictedDuration = m_ulOriginalDelay + m_pSourceInfo->m_ulMaxDuration - m_ulDelay;
  238. }
  239. else
  240. {
  241.     m_ulRestrictedDuration = pRepeatInfo->ulDuration;
  242. }
  243.     }
  244. }
  245. #endif /* HELIX_FEATURE_SMIL_REPEAT */
  246. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  247. m_pStats->Reset();
  248. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  249. m_bReSetup = TRUE;
  250. Setup(pURL, FALSE);
  251.         delete pURL;
  252.     }
  253.     return;
  254. }
  255. // pURL may be in the form of URL
  256. // events will be opened as a separate source by HXPlayer...
  257. HX_RESULT 
  258. HXFileSource::Setup(const CHXURL* pURL, BOOL bAltURL)
  259. {
  260.     HX_RESULT     theErr = HXR_OK;    
  261.     IUnknown*     pUnknown = NULL;
  262.     IUnknown*     pObject = NULL;
  263.     IHXPlugin*     pHXPlugin = NULL;
  264.     mLastError = HXR_OK;
  265.  
  266.     if (!pURL)
  267.     {
  268. return( HXR_INVALID_PATH );
  269.     }                       
  270.     const char* purl = pURL->GetURL();
  271.     if (!purl || !*purl)
  272.     {
  273. return( HXR_INVALID_PATH );
  274.     }                       
  275.     if (!m_bReSetup)
  276.     {
  277. theErr = SetupRegistry();
  278. m_ulOriginalDelay = m_ulDelay;
  279.     }
  280.     ReadPreferences();
  281.     HX_VECTOR_DELETE(m_pszURL);
  282.     HX_DELETE(m_pURL);
  283.     if (!theErr && pURL)
  284.     {
  285. m_pszURL = new char[strlen(purl) + 1];
  286. if (m_pszURL)
  287. {
  288.     strcpy(m_pszURL, purl); /* Flawfinder: ignore */
  289.     m_pURL = new CHXURL(*pURL);
  290.     if( !m_pURL )
  291.     {
  292.         theErr = HXR_OUTOFMEMORY;
  293.     }
  294. }
  295. else
  296. {
  297.     theErr = HXR_OUTOFMEMORY;
  298. }
  299.     }
  300. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  301.     if (!theErr && m_pStats)
  302.     {
  303. // save URL to the registry
  304. if (m_pStats->m_pSourceName && m_pszURL)
  305. {
  306.     m_pStats->m_pSourceName->SetStr((char*)m_pszURL);
  307. }
  308. // update transport mode(local machine)
  309. if (m_pStats->m_pTransportMode && m_pURL)
  310. {
  311.     UINT16 uProtocol = m_pURL->GetProtocol();
  312.     if (uProtocol == httpProtocol)
  313.     {
  314. m_pStats->m_pTransportMode->SetStr("HTTP");
  315.     }
  316.     else
  317.     {
  318. m_pStats->m_pTransportMode->SetStr("Local");
  319.     }
  320. }
  321.     }
  322. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY*/
  323. #if defined(HELIX_FEATURE_ASM) && defined(HELIX_FEATURE_REGISTRY)
  324.     if (!theErr && m_pPlayer && !m_pSimulatedSourceBandwidth && m_pRegistry)
  325.     {
  326. /* Check if the core is used for simulated network playback for
  327.  * local files. This feature is used by the Tools group
  328.  * for Preview mode at different bandwidths.
  329.  */
  330. INT32 lUseNetBandwidth = 0;
  331. if ((m_pRegistry->GetIntByName("UseNetBandwidthForLocalPlayback", 
  332. lUseNetBandwidth) == HXR_OK) && 
  333.     (lUseNetBandwidth == 1))
  334. {
  335.     m_pSimulatedSourceBandwidth = new SourceBandwidthInfo;
  336.     m_pSimulatedSourceBandwidth->AddRef();
  337. }
  338.    }
  339. #endif /* HELIX_FEATURE_ASM && HELIX_FEATURE_REGISTRY*/
  340.     if (!theErr)
  341.     {
  342. const char* pProtocolEnd = HXFindChar(purl,':');
  343. if (!pProtocolEnd)
  344. {
  345.     goto exit;
  346. }
  347. int nLength = pProtocolEnd - purl;
  348. CHXString strProtocol(purl,nLength);
  349. IHXPlugin2Handler* pPlugin2Handler;
  350. if (HXR_OK != m_pEngine->QueryInterface(IID_IHXPlugin2Handler, (void**)&pPlugin2Handler))
  351. {
  352.     theErr = HXR_UNEXPECTED;
  353.     goto exit;
  354. }
  355. if (HXR_OK == pPlugin2Handler->FindPluginUsingStrings(PLUGIN_CLASS, PLUGIN_FILESYSTEM_TYPE, 
  356.     PLUGIN_FILESYSTEMPROTOCOL, (char*)(const char*)strProtocol, NULL, NULL, pUnknown))
  357. {
  358.     pUnknown->QueryInterface(IID_IHXFileSystemObject, (void**) &m_pFSObject);
  359.             HX_RELEASE(pUnknown);
  360. }
  361. else
  362. {
  363.     MergeUpgradeRequest(TRUE, (char*)(const char*) strProtocol);
  364.     theErr = HXR_NO_FILESYSTEM;
  365. }
  366. HX_RELEASE(pPlugin2Handler);
  367. // Initialize the File System plugin...
  368. if (!theErr)
  369. {
  370.     if (HXR_OK != m_pFSObject->QueryInterface(IID_IHXPlugin,(void**)&pHXPlugin))
  371.     {
  372. theErr = HXR_NOT_INITIALIZED;
  373. goto exit;
  374.     }
  375.     if (HXR_OK != pHXPlugin->InitPlugin((IUnknown*) (IHXStreamSource*)this))
  376.     {
  377. theErr = HXR_NOT_INITIALIZED;
  378. goto exit;
  379.     }
  380. }
  381. // Create a FileObject in order to determine the mime-type of the file
  382. if (!theErr)
  383. {
  384.             // Create the file object...
  385.     if (HXR_OK != m_pFSObject->CreateFile(&pObject))
  386.     {
  387. theErr = HXR_NOT_INITIALIZED;
  388. goto exit;
  389.     }
  390.          
  391.     if ((HXR_OK != pObject->QueryInterface(IID_IHXFileObject,
  392. (void**)&m_pFileObject)) ||
  393.         (HXR_OK != pObject->QueryInterface(IID_IHXRequestHandler,
  394. (void**)&m_pRequestHandler)))
  395.     {
  396. theErr = HXR_NOT_INITIALIZED;
  397. goto exit;
  398.     }
  399.     IHXHTTPRedirect* pHttpRedirect = NULL;
  400.             m_pFileObject->QueryInterface(IID_IHXHTTPRedirect, (void**)&pHttpRedirect);
  401.             if (pHttpRedirect)
  402.             {
  403.                 pHttpRedirect->SetResponseObject((IHXHTTPRedirectResponse*) this);
  404.                 pHttpRedirect->Release();
  405.             }
  406.     // set request
  407.     SetRequest(m_pURL, bAltURL);
  408.     
  409.     // we want to protect against the TLC opening another URL
  410.     m_pPlayer->SetModal(TRUE);
  411.     theErr = m_pRequestHandler->SetRequest(m_pRequest);
  412.     m_pPlayer->SetModal(FALSE);
  413.     if (theErr != HXR_OK)
  414.     {
  415. theErr = HXR_NOT_INITIALIZED;
  416. goto exit;
  417.     }
  418.     theErr = ExtendedSetup(purl);
  419. }
  420.     }
  421. exit:
  422.     HX_RELEASE(pHXPlugin);
  423.     HX_RELEASE(pObject);
  424.     if (theErr)
  425.     {
  426. HX_RELEASE(m_pFSObject);
  427.     }
  428.     
  429.     return theErr;
  430. }
  431. HX_RESULT
  432. HXFileSource::ExtendedSetup(const char* pszURL)
  433. {
  434.     HX_RESULT theErr = HXR_OK;
  435.     char* pszTemp = NULL;
  436.     const char* pMimeType = NULL;
  437.     IHXBuffer* pValue = NULL;
  438.     IHXValues* pResponseHeaders = NULL;
  439.     IHXFileMimeMapper* pFileMimeMapper = NULL;
  440.     /* Does the file object support finding of mime types */
  441.     if (HXR_OK == m_pFileObject->QueryInterface(IID_IHXFileMimeMapper,(void**)&pFileMimeMapper))
  442.     {
  443.         if (!m_pMimeFinderResponse)
  444. {
  445.     // Initialize our MimeFinder!
  446.     m_pMimeFinderResponse = new CMimeFinderFileResponse(this);
  447.     if (!m_pMimeFinderResponse)
  448.     {
  449. theErr = HXR_NOT_INITIALIZED;
  450.     }
  451.     else
  452.     {
  453. m_pMimeFinderResponse->AddRef();
  454.     }
  455. }
  456. // Init the file object, and ask for the mime type!
  457. if (!theErr && HXR_OK != pFileMimeMapper->FindMimeType(pszURL, m_pMimeFinderResponse))
  458. {
  459.     theErr = HXR_DOC_MISSING;
  460. }
  461. HX_RELEASE(pFileMimeMapper);
  462.     }
  463.     else
  464.     {
  465. if (HXR_OK == m_pRequest->GetResponseHeaders(pResponseHeaders) &&
  466. pResponseHeaders)
  467. {
  468.     if (HXR_OK == pResponseHeaders->GetPropertyCString("Content-Type", pValue) &&
  469. pValue)
  470.     {
  471. pMimeType = (char*)pValue->GetBuffer();
  472.     }
  473.     HX_RELEASE(pValue);
  474. }
  475. HX_RELEASE(pResponseHeaders);
  476. if (!pMimeType)
  477. {
  478.     if (HXXFile::IsPlusURL(pszURL))
  479.     {
  480. pMimeType = "application/x-pn-plusurl";
  481.     }
  482.     else
  483.     {
  484. // separate options from the URL
  485. pszTemp = (char*) ::HXFindChar(pszURL, '?');
  486. if (pszTemp)
  487. {
  488.     *pszTemp = '';
  489. }
  490.     }
  491. }
  492. FinishSetup(HXR_OK, pMimeType);
  493. theErr = mLastError;
  494.     }
  495.     return theErr;
  496. }
  497. void 
  498. HXFileSource::FinishSetup(HX_RESULT status, const char* pMimeType)
  499. {
  500. #if !defined(HELIX_FEATURE_META)
  501.     m_bValidateMetaDone = TRUE;
  502.     m_bIsMeta = FALSE;
  503. #endif /* HELIX_FEATURE_META */
  504.     if (status == HXR_OK)
  505.     {
  506. if (pMimeType)
  507. {
  508.     HX_VECTOR_DELETE(m_pMimeType);
  509.     m_pMimeType = ::new_string(pMimeType);
  510. }
  511. // detect if this is a valid meta file if we haven't done so
  512. if (!m_bValidateMetaDone)
  513. {
  514.     AttempToLoadFilePlugin(RAM_MIMETYPE);
  515. }
  516. #if defined(HELIX_FEATURE_SDPLITE)
  517.         // retrieve the whole SDP file without SDP fileformat/renderer which
  518.         // requires basic group&track
  519. else if (m_pMimeType && 0 == strcasecmp(m_pMimeType, "application/sdp"))
  520.         {
  521.             if (!m_pFileReader)
  522.             {
  523.                 m_pFileReader = new CFileReader(this);
  524.                 HX_ADDREF(m_pFileReader);
  525.             }
  526.             if (m_pFileReader)
  527.             {
  528.                 m_pFileReader->GetFile(m_pFileObject);
  529.             }
  530.             return;
  531.         }
  532. #endif /* HELIX_FEATURE_SDPLITE */
  533. // we have already validated the file and know whether
  534. // it is a meta or not
  535.         else
  536. {
  537.     if (m_bIsMeta)
  538.     {
  539. AttempToLoadFilePlugin(RAM_MIMETYPE);
  540.     }
  541.     else
  542.     {
  543.                 // Call recognizer here if we do not have a definite
  544.                 // mimetype from the filesytem
  545.                 if ((!m_pMimeType || m_pMimeType == "*") && !m_pFileRecognizer)
  546.                 {
  547.                     m_pFileRecognizer = new CHXFileRecognizer;
  548.                     if (m_pFileRecognizer)
  549.                     {
  550.                         m_pFileRecognizer->AddRef();
  551.                         if (!m_pMimeFinderResponse)
  552.                         {
  553.                             m_pMimeFinderResponse = new CMimeFinderFileResponse(this);                        
  554.                             HX_ADDREF(m_pMimeFinderResponse);
  555.                         }
  556.                         if (m_pMimeFinderResponse)
  557.                         {
  558.                             m_pFileRecognizer->GetMimeType(m_pFileObject, 
  559.                                                            (IHXFileRecognizerResponse*)m_pMimeFinderResponse);
  560.                             return;
  561.                         }
  562.                         else
  563.                         {
  564.                             HX_DELETE(m_pFileRecognizer); 
  565.                         }
  566.                     }
  567.                 }
  568.                 
  569.                 AttempToLoadFilePlugin(m_pMimeType);
  570.     }
  571. }
  572.     }
  573.     else if (!mLastError)
  574.     {
  575. mLastError = status;
  576. ReportError(mLastError);
  577.     }
  578. }
  579. void 
  580. HXFileSource::AttempToLoadFilePlugin(const char* pMimeType)
  581. {
  582.     char*   pExtension = NULL;
  583.     char*   pszTemp = NULL;
  584.     char*   pszURL = NULL;
  585.     HX_RESULT theErr = HXR_OK;
  586.     IUnknown* pUnknown = NULL;
  587.     
  588.     if (!m_bValidateMetaDone)
  589.     {
  590. pExtension = "ram";
  591.     }
  592.     else
  593.     {
  594. // This will fix up any redirected 
  595. GetURL();
  596.     
  597. // make a copy of the URL
  598. pszURL = new char[strlen(m_pszURL)+1];
  599. memset(pszURL, 0, strlen(m_pszURL)+1);
  600. strcpy(pszURL, m_pszURL); /* Flawfinder: ignore */
  601. // separate fragment from the URL
  602. pszTemp = (char*) ::HXFindChar(pszURL, '#');
  603. if (pszTemp)
  604. {
  605.     *pszTemp = '';
  606. }
  607. // separate options from the URL
  608. pszTemp = (char*) ::HXFindChar(pszURL, '?');
  609. if (pszTemp)
  610. {
  611.     *pszTemp = '';
  612. }
  613. // load plugin 
  614. pExtension = strrchr(pszURL, '.');
  615.     
  616. if (pExtension)
  617. {
  618.     /* get past . */
  619.     pExtension++;
  620. }
  621. if (pExtension)
  622. {
  623.     HX_VECTOR_DELETE(m_pExtension);
  624.     m_pExtension = ::new_string(pExtension);
  625. }
  626.     }
  627.     if (!m_pCurrentFileFormatUnk)
  628.     {
  629. IHXPluginHandler3* pPlugin2Handler3 = NULL;
  630. HX_VERIFY(HXR_OK ==
  631.     m_pPlayer->m_pPlugin2Handler->QueryInterface(IID_IHXPluginHandler3, (void**) &pPlugin2Handler3));
  632. if (pMimeType)
  633. {
  634.     pPlugin2Handler3->FindGroupOfPluginsUsingStrings(PLUGIN_CLASS, PLUGIN_FILEFORMAT_TYPE, 
  635.     PLUGIN_FILEMIMETYPES, (char*)pMimeType, 0, 0, m_pFileFormatEnumerator);
  636. }
  637. if (!m_pFileFormatEnumerator)
  638. {
  639.     pPlugin2Handler3->FindGroupOfPluginsUsingStrings(PLUGIN_CLASS, PLUGIN_FILEFORMAT_TYPE, 
  640. PLUGIN_FILEEXTENSIONS, pExtension, 0 ,0, m_pFileFormatEnumerator);
  641. }
  642. HX_RELEASE(pPlugin2Handler3);
  643. if (m_pFileFormatEnumerator)
  644. {
  645.     m_pFileFormatEnumerator->GetNextPlugin(m_pCurrentFileFormatUnk, NULL);
  646.     HX_ASSERT(m_pCurrentFileFormatUnk != NULL);
  647. }
  648.     }
  649.     if (!m_pCurrentFileFormatUnk)
  650.     {
  651. if (!m_bDefaultAltURL)
  652. {
  653.     theErr = HXR_NO_FILEFORMAT;
  654. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  655.     IHXUpgradeCollection* pUpgradeCollection = NULL;
  656.     if(m_pPlayer)
  657. m_pPlayer->QueryInterface(IID_IHXUpgradeCollection, (void**)&pUpgradeCollection);
  658.     if(pUpgradeCollection)
  659.     {
  660. IHXBuffer* pPluginID = (IHXBuffer*) new CHXBuffer;
  661. pPluginID->AddRef();
  662. if (pMimeType && !(*pMimeType == '*'))
  663. {
  664.     pPluginID->Set((const UINT8*)pMimeType, strlen(pMimeType) + 1);
  665. }
  666. else if (pExtension)
  667. {
  668.     // return file extension if mimeType is unknown
  669.     pPluginID->Set((const UINT8*)pExtension, strlen(pExtension) + 1);
  670. }
  671. else
  672. {
  673.     pPluginID->Set((const UINT8*)"Unknown FileFormat", strlen("Unknown FileFormat") + 1);
  674. }
  675. pUpgradeCollection->Add(eUT_Required, pPluginID, 0, 0);
  676. pPluginID->Release();
  677. pUpgradeCollection->Release();
  678.     }
  679. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  680. }
  681. else
  682. {
  683.     theErr = HXR_INVALID_FILE;
  684. }
  685.     }
  686.     // initialize fileformat plugins...
  687.     if (!theErr)
  688.     {
  689. theErr = InitializeFileFormat();
  690.     }
  691.     HX_VECTOR_DELETE(pszURL);
  692.     // if there is an error, make sure there is no m_pCurrentFileFormatUnk...
  693.     // if m_pCurrentFileFormatUnk is not NULL, it means we need to try 
  694.     // the next plugin that supports this mimetype.
  695.     // ignore error in this case.
  696.     if (theErr && !m_pCurrentFileFormatUnk)
  697.     {
  698. mLastError = theErr;
  699. CheckForDefaultUpgrade(theErr);
  700. // merge any upgrade requests for this source to the player
  701. MergeUpgradeRequest(m_bAddDefaultUpgrade, m_pDefaultUpgradeString);
  702. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  703. if (theErr != HXR_NO_FILEFORMAT)
  704. #endif
  705. {
  706.     ReportError(theErr);
  707.     DoCleanup();
  708. }
  709.     }
  710. }
  711. HX_RESULT
  712. HXFileSource::InitializeFileFormat()
  713. {
  714.     HX_RESULT theErr = HXR_OK;
  715.     HX_RESULT resultInitFF = HXR_OK;
  716.     IHXRequest* pRequest = NULL;
  717.     IHXPlugin* pPlugin = NULL;
  718.     
  719.     HX_ASSERT(m_pCurrentFileFormatUnk != NULL);
  720.     if (m_pCurrentFileFormatUnk)
  721.     {
  722. HX_VERIFY(HXR_OK ==
  723.     m_pCurrentFileFormatUnk->QueryInterface(IID_IHXFileFormatObject, (void**) &m_pFFObject));
  724.     }
  725.     
  726.     HX_RELEASE(m_pCurrentFileFormatUnk);
  727.     m_bCurrentFileFormatUnkInUse = FALSE;
  728.     HX_ASSERT(m_pFFObject != NULL);
  729.     if (!m_pFFObject)
  730.     {
  731. return HXR_INVALID_FILE; //??
  732.     }
  733.     // we keep RAM FF object around by AddRef()
  734.     // to avoid self-destruct in ::InitDone when it's not a RAM
  735.     // It will be released in ::FinishSetup().
  736.     
  737.     if (!m_bValidateMetaDone)
  738.     {
  739. HX_ASSERT(!m_pRAMFFObject);
  740. m_pRAMFFObject = m_pFFObject;
  741. m_pRAMFFObject->AddRef();
  742.     }
  743.     
  744.     if (HXR_OK != m_pFFObject->QueryInterface(IID_IHXPlugin,(void**)&pPlugin))
  745.     {
  746. theErr = HXR_NOT_INITIALIZED;
  747. goto exit;
  748.     }
  749.     if (HXR_OK != pPlugin->InitPlugin((IUnknown*) (IHXStreamSource*)this))
  750.     {
  751. theErr = HXR_NOT_INITIALIZED;
  752. goto exit;
  753.     }
  754.     if (m_pRequestHandler->GetRequest(pRequest) != HXR_OK)
  755.     {
  756. theErr = HXR_NOT_INITIALIZED;
  757. goto exit;
  758.     }
  759.     if (HXR_OK != (resultInitFF=m_pFFObject->InitFileFormat(pRequest,
  760.                                       this,
  761.                                       m_pFileObject)) )
  762.     {
  763. if(HXR_UNSUPPORTED_VIDEO == resultInitFF ||
  764.    HXR_UNSUPPORTED_AUDIO == resultInitFF ||
  765.    HXR_DOC_MISSING == resultInitFF)
  766. {
  767.     theErr = resultInitFF;
  768. }
  769. else
  770. {
  771.     theErr = HXR_INVALID_FILE; //HXR_NOT_INITIALIZED;
  772. }
  773. goto exit;
  774.     }
  775. exit:
  776.     HX_RELEASE(pRequest);
  777.     HX_RELEASE(pPlugin);
  778.     if (theErr)
  779.     {
  780. /* do we need to try the next one! */
  781. if (!m_pCurrentFileFormatUnk && m_pFileFormatEnumerator)
  782. {
  783.     m_pFileFormatEnumerator->GetNextPlugin(m_pCurrentFileFormatUnk, NULL);
  784.     if (m_pCurrentFileFormatUnk && m_pSourceInfo)
  785.     {
  786. m_pSourceInfo->ScheduleProcessCallback();
  787.     }
  788. }
  789.     }
  790.     return theErr;
  791. }
  792. HX_RESULT 
  793. HXFileSource::DoCleanup(EndCode endCode)
  794. {
  795.     /* UnRegister any previously registered source */
  796.     if (m_pSourceInfo)
  797.     {
  798.         m_pSourceInfo->UnRegister();
  799.     }
  800.     CleanupFileObjects();
  801.     HX_RELEASE(m_pCurrentFileFormatUnk);
  802.     m_bCurrentFileFormatUnkInUse = FALSE;
  803.     HX_RELEASE(m_pFileFormatEnumerator);
  804. #if defined(HELIX_FEATURE_ASM)
  805.     HX_RELEASE(m_pSimulatedSourceBandwidth);
  806. #endif /* HELIX_FEATURE_ASM */
  807.     HX_VECTOR_DELETE(m_pMimeType);
  808.     HX_VECTOR_DELETE(m_pExtension);
  809.     HX_VECTOR_DELETE(m_pDefaultUpgradeString);    
  810.     m_bAddDefaultUpgrade = FALSE;
  811.     HX_RELEASE(m_pFileRecognizer);
  812. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  813.     /* Reason to add this code is because in FileSource 
  814.      * we create/delete it while in NetSource
  815.      * case, Protocol creates/deletes it
  816.      */
  817.     for (CHXMapLongToObj::Iterator i = mStreamInfoTable->Begin();
  818.          i != mStreamInfoTable->End(); ++i) 
  819.     {    
  820. STREAM_INFO* sInfo = (STREAM_INFO*) (*i);
  821. if (sInfo)
  822. {
  823.     HX_DELETE (sInfo->m_pStats);
  824. }
  825.     }
  826. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY*/
  827.     HXSource::DoCleanup();
  828.     return HXR_OK;
  829. }
  830. void
  831. HXFileSource::ReportError(HX_RESULT theErr)
  832. {
  833.     CHXString DecodedURL;
  834.     CHXURL::decodeURL(m_pURL->GetURL(), DecodedURL);
  835.     m_pPlayer->ReportError( this, theErr, DecodedURL );
  836. }
  837. void
  838. HXFileSource::CleanupFileObjects()
  839. {
  840.     HX_RELEASE (m_pFSObject);
  841.     if (m_pFFObject)
  842.     {
  843. m_pFFObject->Close();
  844. HX_RELEASE (m_pFFObject);
  845.     }    
  846.     
  847.     HX_RELEASE (m_pFileResponse);
  848.     if (m_pFileObject)
  849.     {
  850. m_pFileObject->Close();
  851. HX_RELEASE (m_pFileObject);
  852.     }
  853.     HX_RELEASE (m_pRequestHandler);
  854.     HX_RELEASE (m_pMimeFinderResponse);
  855. }
  856. HX_RESULT
  857. HXFileSource::DoSeek(ULONG32 seekTime)
  858. {
  859.     /* Add any start time to seek time */
  860.     if (seekTime >= m_ulDelay)
  861.     {
  862. seekTime    -= m_ulDelay;
  863. m_bDelayed   = FALSE;
  864.     }
  865.     else
  866.     {
  867. seekTime = 0;
  868. /* This source has not been even started yet...
  869.  * Do not attempt to seek it if the start time = 0
  870.  */
  871. if (m_bDelayed && m_ulStartTime == 0 && !m_bSourceEnd)
  872. {
  873.     // will start pre-fetch again in TryResume()
  874.     if (!m_bIsPreBufferingDone)
  875.     {
  876. m_bIsPreBufferingStarted = FALSE;
  877. // will be registered again in DoResume() or TryResume()
  878. if (m_pSourceInfo)
  879. {
  880.     m_pSourceInfo->UnRegister();
  881. }
  882.     }
  883.     return HXR_OK;
  884. }
  885. m_bDelayed = TRUE;
  886.     }
  887.     seekTime += m_ulStartTime;
  888.     /* Are we seeking past the last expected packet time?
  889.      * If so, don't bother... and mark this source as done
  890.      */
  891.     HX_ASSERT(m_llLastExpectedPacketTime < MAX_UINT32);
  892.     // XXX HP make sure the source has been initialized otherwise
  893.     // m_llLastExpectedPacketTime could be 0 and we could falsely
  894.     // mark the source ended
  895.     if (m_bInitialized && !mLiveStream && seekTime >= INT64_TO_UINT32(m_llLastExpectedPacketTime))
  896.     {
  897. if (m_pSourceInfo && m_pSourceInfo->m_bSeekToLastFrame)
  898. {
  899.     seekTime = INT64_TO_UINT32(m_llLastExpectedPacketTime);
  900. }
  901. else
  902. {
  903.     m_bSourceEnd = TRUE;
  904.     m_bForcedSourceEnd = TRUE;
  905.     AdjustClipBandwidthStats(FALSE);
  906.     goto cleanup;
  907. }
  908.     }
  909.     m_bInitialBuffering = TRUE;
  910.     m_bForcedSourceEnd = FALSE;
  911.     m_uActiveStreams = m_uNumStreams; 
  912.     m_bIsPreBufferingStarted = FALSE;
  913.     m_bIsPreBufferingDone = FALSE;
  914.     if (m_nSeeking == 0)
  915.     {
  916. m_nSeeking++;
  917.     }
  918. #if defined(HELIX_FEATURE_RECORDCONTROL)
  919.     if (m_pRecordControl && m_pRecordControl->Seek(seekTime) == HXR_OK &&
  920. m_bPlayFromRecordControl)
  921.     {
  922. m_pBufferManager->DoSeek(seekTime, TRUE);
  923. SeekDone(HXR_OK);
  924.     }
  925.     else
  926. #endif /* HELIX_FEATURE_RECORDCONTROL */
  927.     {
  928. m_bSourceEnd = FALSE;
  929. m_pBufferManager->DoSeek(seekTime, FALSE);
  930. if (HXR_OK != m_pFFObject->Seek(seekTime))
  931. {
  932.     if (m_nSeeking)
  933.     {
  934. m_nSeeking--;
  935.     }
  936. }
  937.     }
  938.     m_llLastFillEndTime = 0;   
  939. cleanup:
  940.     return HXR_OK;
  941. }
  942. HX_RESULT
  943. HXFileSource::DoPause(void)
  944. {
  945.     if (m_bPaused)
  946.     {
  947. return HXR_OK;
  948.     }
  949.     /* Only if it is an external pause */
  950.     if (!m_bSourceEnd && !m_bDelayed && m_pBufferManager)
  951.     {
  952. m_pBufferManager->DoPause();
  953.     }
  954.     m_bPaused = TRUE;
  955.     return HXR_OK;
  956. }
  957. HX_RESULT   
  958. HXFileSource::StartInitialization(void)
  959. {
  960.     m_bFastStartInProgress = TRUE;
  961.     m_pBufferManager->DoResume();
  962.     if (m_pSourceInfo)
  963.     {
  964. m_pSourceInfo->Resumed();
  965.     }
  966.     return HXR_OK;
  967. }
  968. HX_RESULT   
  969. HXFileSource::DoResume(void)
  970. {
  971.     HX_RESULT theErr = HXR_OK;
  972.     m_bFastStartInProgress = FALSE;
  973.     /* This may happen if a new source is added from SMIL renderer during 
  974.      * initialization of exisitng sources. We will eventually call Resume 
  975.      * on this source once it is initialized in SourceInfo::ProcessIdle
  976.      */
  977.     if (!m_bInitialized || (m_pSourceInfo && !m_pSourceInfo->IsInitialized()))
  978.     {
  979. return HXR_OK;
  980.     }
  981.     if (m_bSourceEnd || CanBeResumed())
  982.     {
  983. m_bResumePending = FALSE;
  984. if (!m_bSourceEnd)
  985. {
  986.     m_pBufferManager->DoResume();
  987. }
  988. // resume the audio streams if the source is added
  989. // while the player is in play mode
  990. // CAUTION: this will cause rewind in audio service
  991. if (m_bFirstResume && m_pPlayer->IsPlaying() &&
  992.     m_ulDelay <= m_pPlayer->GetInternalCurrentPlayTime())
  993. {
  994.     ResumeAudioStreams();
  995. }
  996. m_bFirstResume = FALSE;
  997. m_bPaused = FALSE;
  998. if (m_pSourceInfo)
  999. {
  1000.     m_pSourceInfo->Resumed();
  1001. }
  1002. if (!m_bSourceEnd)
  1003. {
  1004.     theErr = FillBuffers();
  1005. }
  1006.     }
  1007.     if (!theErr && !m_bIsActive && !m_bDelayed &&
  1008. m_pPlayer->GetInternalCurrentPlayTime() >= m_ulDelay)
  1009.     {
  1010. AdjustClipBandwidthStats(TRUE);
  1011.     }
  1012.     if (theErr == HXR_AT_END)
  1013.     {
  1014. SetEndOfClip();
  1015. theErr = HXR_OK;
  1016.     }
  1017.     return theErr;
  1018. }
  1019. /************************************************************************
  1020.  * Method:
  1021.  *     IHXPendingStatus::GetStatus
  1022.  * Purpose:
  1023.  *     Called by the user to get the current pending status from an object
  1024.  */
  1025. STDMETHODIMP
  1026. HXFileSource::GetStatus
  1027. (
  1028.     REF(UINT16) uStatusCode, 
  1029.     REF(IHXBuffer*) pStatusDesc, 
  1030.     REF(UINT16) ulPercentDone
  1031. )
  1032. {
  1033.     HX_RESULT hResult = HXR_OK;
  1034.     IHXPendingStatus* pStatus = NULL;
  1035.     UINT16  buffer = 100;
  1036.     UINT16  statusCode = HX_STATUS_READY;
  1037.     UINT16  percentDone = 0;
  1038.     uStatusCode     = HX_STATUS_READY;
  1039.     pStatusDesc     = 0;
  1040.     ulPercentDone   = 0;
  1041.     
  1042.     if (m_bDelayed)
  1043.     {
  1044. return HXR_OK;
  1045.     }
  1046.     if (m_bSourceEnd)
  1047.     {
  1048. if (!IsRebufferDone())
  1049. {
  1050.     uStatusCode = HX_STATUS_BUFFERING;
  1051.     ulPercentDone = 99;
  1052. }
  1053. else
  1054. {
  1055.     if (m_bInitialBuffering)
  1056.     {
  1057. InitialBufferingDone();
  1058.     }
  1059.     m_ulLastBufferingReturned = 100;
  1060.     uStatusCode = HX_STATUS_READY;
  1061. }
  1062. return HXR_OK;
  1063.     }
  1064.     if (m_bInitialized)
  1065.     {
  1066. if (m_bFirstResume)
  1067. {
  1068.     uStatusCode     = HX_STATUS_INITIALIZING;
  1069.     return HXR_OK;
  1070. }
  1071. m_pBufferManager->GetStatus(uStatusCode, 
  1072.     pStatusDesc,
  1073.     ulPercentDone);
  1074. buffer = ulPercentDone;
  1075. /* We only aggregate buffering from a lower level if we are in a buffering mode.
  1076.  * Reason: Once the initial bufering is done, we go in buffering more ONLY IF the
  1077.  * renderer tells us that it is in a panic state and we run out of packets.
  1078.  */
  1079. if (buffer == 100 && !m_bInitialBuffering)
  1080. {     
  1081.     // Rebuffer requested by the Renderer might not be
  1082.     // done yet
  1083.     if (!IsRebufferDone())
  1084.     {
  1085. uStatusCode = HX_STATUS_BUFFERING;
  1086. ulPercentDone = 99;
  1087.     }
  1088.     else
  1089.     {
  1090. uStatusCode = HX_STATUS_READY;
  1091.     }
  1092.     return HXR_OK;
  1093. }
  1094.     }
  1095.     if (m_pFFObject)
  1096.     {
  1097. if (HXR_OK != m_pFFObject->QueryInterface(IID_IHXPendingStatus, (void**)&pStatus))
  1098. {
  1099.     goto exit;
  1100. }
  1101. if (HXR_OK != pStatus->GetStatus(statusCode, pStatusDesc, percentDone))
  1102. {
  1103.     goto exit;
  1104. }
  1105.     }
  1106.     else if (m_pFileObject)
  1107.     {
  1108. if (HXR_OK != m_pFileObject->QueryInterface(IID_IHXPendingStatus, (void**)&pStatus))
  1109. {
  1110.     goto exit;
  1111. }
  1112. if (HXR_OK != pStatus->GetStatus(statusCode, pStatusDesc, percentDone))
  1113. {
  1114.     goto exit;
  1115. }
  1116.     }
  1117. exit:
  1118.     
  1119.     if (HX_STATUS_CONTACTING == statusCode)
  1120.     {
  1121. uStatusCode = HX_STATUS_CONTACTING;
  1122. ulPercentDone = 0;
  1123.     }
  1124.     else if (!m_bInitialized)
  1125.     {
  1126. uStatusCode = HX_STATUS_INITIALIZING;
  1127. ulPercentDone = 0;
  1128.     }
  1129.     else if (HX_STATUS_READY == statusCode && 100 == buffer)
  1130.     {
  1131. uStatusCode = HX_STATUS_READY;
  1132. ulPercentDone = 0;
  1133. m_ulLastBufferingReturned = 100;
  1134.     }
  1135.     else
  1136.     {
  1137. uStatusCode = HX_STATUS_BUFFERING;
  1138. if (HX_STATUS_READY == statusCode)
  1139. {
  1140.     ulPercentDone = (UINT16)buffer;
  1141. }
  1142. else
  1143. {
  1144.     ulPercentDone = (UINT16)((buffer + percentDone) * 0.5);
  1145. }
  1146. // Do not go back
  1147. if (ulPercentDone < m_ulLastBufferingReturned && m_ulLastBufferingReturned != 100)
  1148. {
  1149.     ulPercentDone = (UINT16) m_ulLastBufferingReturned;
  1150. }
  1151. else
  1152. {
  1153.     m_ulLastBufferingReturned = ulPercentDone;
  1154. }
  1155.     }
  1156.     HX_RELEASE(pStatus);
  1157.   
  1158.     ulPercentDone = ulPercentDone <= 100 ? (UINT16)ulPercentDone : 100;
  1159.     if (m_bInitialBuffering && HX_STATUS_READY == uStatusCode)
  1160.     {
  1161. InitialBufferingDone();
  1162.     }
  1163.     /* If we had a delayed start, we do not want to show that we are
  1164.      * in buffering state UNLESS it is really time to give out packets
  1165.      * and we do not have 
  1166.      */
  1167.     if (m_bInitialized && m_ulDelay > 0 && 
  1168. uStatusCode == HX_STATUS_BUFFERING && 
  1169. ulPercentDone < 100)
  1170.     {
  1171. UINT32 ulCurrentTime = m_pPlayer->GetInternalCurrentPlayTime();
  1172. if ((ulCurrentTime + MIN_BUFFERTIME_BEFORE_DELAY) < m_ulDelay)
  1173. {
  1174.     ulPercentDone = 100;
  1175. }
  1176.     }
  1177.     return hResult;
  1178. }
  1179. UINT16
  1180. HXFileSource::GetNumStreams(void)
  1181. {
  1182.     HX_ASSERT(m_bInitialized);
  1183.     
  1184.     return m_uNumStreams;
  1185. }
  1186. HX_RESULT
  1187. HXFileSource::GetStreamInfo(ULONG32     ulStreamNumber,
  1188.      STREAM_INFO*&  theStreamInfo)
  1189. {
  1190.     HX_RESULT theErr = HXR_OK;
  1191.     STREAM_INFO* lpStreamInfo = 0;
  1192.     if (!mStreamInfoTable->Lookup((LONG32)ulStreamNumber, (void *&)lpStreamInfo))
  1193.     {
  1194. theErr = HXR_INVALID_PARAMETER;
  1195.     }
  1196.     theStreamInfo = lpStreamInfo;
  1197.     return theErr;
  1198. }
  1199. HX_RESULT    
  1200. HXFileSource::GetEvent(UINT16 usStreamNumber, CHXEvent*& theEvent)
  1201. {
  1202.     HX_RESULT theErr = HXR_OK;
  1203.     HX_TRACE("HXFileSource::GetEvent");
  1204.     theEvent = 0;
  1205.     
  1206.     if (!m_bInitialized)
  1207.     {
  1208. return HXR_NOT_INITIALIZED;
  1209.     }
  1210.     if (mLastError != HXR_OK)
  1211.     {
  1212. return mLastError;
  1213.     }
  1214.     if (m_bPaused && m_bDelayed)
  1215.     {
  1216. if (TryResume())
  1217. {
  1218.     m_pPlayer->RegisterSourcesDone();
  1219.          DoResume();
  1220. }
  1221. else
  1222. {
  1223.     return HXR_NO_DATA;
  1224. }
  1225.     }
  1226.     STREAM_INFO * lpStreamInfo;
  1227.     if (!mStreamInfoTable->Lookup((LONG32) usStreamNumber, (void *&) lpStreamInfo))
  1228.     {
  1229. theErr = HXR_INVALID_PARAMETER;
  1230. return theErr;
  1231.     }
  1232. #if defined(HELIX_FEATURE_RECORDCONTROL)
  1233.     if (m_bPlayFromRecordControl && m_pRecordControl)
  1234.     {
  1235. IHXPacket* pPacket = NULL;
  1236. HX_ASSERT(m_pRecordControl);
  1237. theErr = m_pRecordControl->GetPacket(usStreamNumber, pPacket);
  1238. if(theErr == HXR_OK)
  1239. {
  1240.             UINT32 streamPreRoll = max(lpStreamInfo->BufferingState().GetMinPrerollInMs(),1000);
  1241.     INT64 llPacketTime = 
  1242. lpStreamInfo->BufferingState().CreateINT64Timestamp(pPacket->GetTime());
  1243.     theEvent = new CHXEvent(pPacket, 
  1244.     GetEventBeginTime(llPacketTime, 
  1245.       streamPreRoll));
  1246.     if(theEvent) 
  1247. theEvent->SetTimeOffset(m_ulStartTime - m_ulDelay); 
  1248.     else
  1249. theErr = HXR_OUTOFMEMORY;
  1250.     if(m_pBufferManager)
  1251. m_pBufferManager->UpdateCounters(pPacket);
  1252.     HX_RELEASE(pPacket);
  1253. }
  1254. else
  1255. {
  1256.     if(theErr == HXR_NO_DATA && (m_bSourceEnd || lpStreamInfo->m_bSrcStreamDone))
  1257. theErr = HXR_AT_END;
  1258.     if(theErr == HXR_NO_DATA)
  1259.     {
  1260. if (lpStreamInfo->m_unNeeded > 0 &&
  1261.     lpStreamInfo->m_unNeeded != lpStreamInfo->m_unAvailable)
  1262. {
  1263.     // Re-initialize buffering
  1264.     m_pBufferManager->ReBuffer();
  1265.     FillBuffers();
  1266.     theErr = HXR_BUFFERING;
  1267. }
  1268.     }
  1269. }
  1270. return theErr;
  1271.     }
  1272. #endif /* HELIX_FEATURE_RECORDCONTROL */
  1273.     // get the packet list for this stream
  1274.     CHXEventList  * lEventList = &lpStreamInfo->m_EventList;
  1275.     // do we need to fill buffers...
  1276.     if (lEventList->GetNumEvents() == 0)
  1277.     {
  1278. theErr = FillBuffers();
  1279. if (theErr == HXR_AT_END)
  1280. {
  1281.     SetEndOfClip();
  1282.     theErr = HXR_OK;
  1283. }
  1284. // check if we have packets now...
  1285. if (!theErr && lEventList->GetNumEvents() == 0)
  1286. {
  1287.     if (m_bSourceEnd || lpStreamInfo->m_bSrcStreamDone)
  1288.     {
  1289. return HXR_AT_END;     
  1290.     }
  1291.     else
  1292.     {
  1293. if (lpStreamInfo->m_unNeeded > 0 &&
  1294.     lpStreamInfo->m_unNeeded != lpStreamInfo->m_unAvailable)
  1295. {
  1296.     // Re-initialize buffering
  1297.     m_pBufferManager->ReBuffer();
  1298.     FillBuffers();
  1299.     return HXR_BUFFERING;
  1300. }
  1301. return HXR_NO_DATA;
  1302.     }
  1303. }
  1304.     }
  1305.     if (!theErr)
  1306.     {
  1307. // this event will be deleted by the player...
  1308. theEvent = lEventList->RemoveHead();
  1309.     }
  1310. #ifdef LOSS_HACK
  1311.     if (m_ulLossHack > 0 && ((UINT32) (rand() % 100) < m_ulLossHack) &&
  1312. !theErr && theEvent && !(theEvent->GetPacket())->IsLost())
  1313.     {
  1314. GenerateFakeLostPacket(theEvent);
  1315. /* Update the stats */
  1316. if (lpStreamInfo->m_ulReceived > 0)
  1317. {
  1318.     lpStreamInfo->m_ulReceived--;
  1319.     lpStreamInfo->m_ulLost++;
  1320. }
  1321.     }
  1322. #endif /* LOSS_HACK */
  1323.     return theErr;
  1324. }
  1325. void 
  1326. HXFileSource::ReBuffer()
  1327. {
  1328.     UINT32  ulRemainToBufferInMs = 0;
  1329.     UINT32  ulRemainToBuffer = 0;
  1330.     m_pBufferManager->GetRemainToBuffer(ulRemainToBufferInMs,
  1331. ulRemainToBuffer);
  1332.     if 
  1333.     (
  1334. ulRemainToBufferInMs == 0 &&
  1335. ulRemainToBuffer == 0
  1336.     )
  1337.     {
  1338. m_pBufferManager->ReBuffer();
  1339. FillBuffers();
  1340.     }
  1341. }
  1342. BOOL
  1343. HXFileSource::IsStatisticsReady(void)
  1344. {
  1345.     return HXR_OK;
  1346. }
  1347. HX_RESULT
  1348. HXFileSource::UpdateRegistry(UINT32 ulRegistryID)
  1349. {
  1350.     HX_RESULT     theErr = HXR_OK;
  1351. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  1352.     UINT32     ulRegId = 0;
  1353.     char     szRegName[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
  1354.     IHXBuffer*     pParentName = NULL;
  1355.     STREAM_INFO*    pStreamInfo = NULL;
  1356.     CHXMapLongToObj::Iterator ndxStream;
  1357.     m_ulRegistryID = ulRegistryID;
  1358.     if (!m_pStats)
  1359.     {
  1360. SetupRegistry();
  1361.     }
  1362.     else
  1363.     {
  1364. if (m_pSourceInfo     &&
  1365.     m_pSourceInfo->m_bLeadingSource &&
  1366.     !m_pSourceInfo->m_pRepeatList)
  1367. {
  1368.             //Copy over the 'next group' stats.
  1369.             SOURCE_STATS* pTmpSourceStats = new SOURCE_STATS(m_pRegistry, m_ulRegistryID);
  1370.             *pTmpSourceStats = *m_pStats;
  1371.             
  1372.     ndxStream = mStreamInfoTable->Begin();
  1373.     for(; ndxStream != mStreamInfoTable->End(); ++ndxStream)
  1374.     {
  1375. pStreamInfo = (STREAM_INFO*) (*ndxStream);
  1376. if (m_pRegistry     && 
  1377.     pTmpSourceStats &&
  1378.     HXR_OK == m_pRegistry->GetPropName(pTmpSourceStats->m_ulRegistryID, pParentName))
  1379. {
  1380.     SafeSprintf(szRegName, MAX_DISPLAY_NAME, "%s.Stream%ld", pParentName->GetBuffer(), 
  1381.     pStreamInfo->m_uStreamNumber);
  1382.     ulRegId = m_pRegistry->GetId(szRegName);
  1383.     if (!ulRegId)
  1384.     {
  1385. ulRegId = m_pRegistry->AddComp(szRegName);
  1386.     }
  1387.     STREAM_STATS* pTmpStreamStats = new STREAM_STATS(m_pRegistry, ulRegId);
  1388.                     //Copy over the "next-group" stats
  1389.                     *pTmpStreamStats = *pStreamInfo->m_pStats;
  1390.                     HX_DELETE(pStreamInfo->m_pStats);
  1391.                     pStreamInfo->m_pStats = pTmpStreamStats;
  1392. }
  1393. HX_RELEASE(pParentName);
  1394.     }
  1395.             HX_DELETE(m_pStats);
  1396.             m_pStats = pTmpSourceStats;
  1397. }
  1398. else if (m_pStatsManager)
  1399. {
  1400.     m_pStatsManager->UpdateRegistry(m_ulRegistryID);
  1401. }
  1402.     }
  1403. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  1404.     return theErr;
  1405. }
  1406. HX_RESULT
  1407. HXFileSource::UpdateStatistics(void)
  1408. {
  1409. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  1410.     ULONG32 ulSourceLost = 0;    
  1411.     ULONG32 ulSourceTotal = 0;    
  1412.     ULONG32 ulSourceReceived = 0;   
  1413.     ULONG32 ulSourceNormal = 0;       
  1414.     ULONG32 ulSourceBandwidth = 0;   
  1415.   
  1416.     CHXMapLongToObj::Iterator ndxStream = mStreamInfoTable->Begin();
  1417.     for (; ndxStream != mStreamInfoTable->End(); ++ndxStream) 
  1418.     {
  1419.         STREAM_INFO* pStreamInfo   = (STREAM_INFO*) (*ndxStream);
  1420.         ULONG32 ulStreamTotal = 0;
  1421.         ULONG32 ulStreamReceived = 0;
  1422.         ULONG32 ulStreamNormal = 0;
  1423.     
  1424. // update the statistics in the registry
  1425. ulStreamNormal = pStreamInfo->m_ulReceived;
  1426. ulStreamReceived = ulStreamNormal;
  1427. ulStreamTotal = ulStreamNormal + pStreamInfo->m_ulLost;
  1428. pStreamInfo->m_pStats->m_pNormal->SetInt((INT32)ulStreamNormal);
  1429. pStreamInfo->m_pStats->m_pReceived->SetInt((INT32)ulStreamReceived);     
  1430. pStreamInfo->m_pStats->m_pLost->SetInt((INT32)pStreamInfo->m_ulLost);
  1431. pStreamInfo->m_pStats->m_pTotal->SetInt((INT32)ulStreamTotal);
  1432. ulSourceTotal += ulStreamTotal;
  1433. ulSourceReceived += ulStreamReceived;
  1434. ulSourceNormal += ulStreamNormal;
  1435. ulSourceLost += pStreamInfo->m_ulLost;
  1436. ulSourceBandwidth += pStreamInfo->m_pStats->m_pClipBandwidth->GetInt();
  1437.     }
  1438.     if (m_pStats->m_pNormal) m_pStats->m_pNormal->SetInt((INT32)ulSourceNormal);
  1439.     if (m_pStats->m_pReceived) m_pStats->m_pReceived->SetInt((INT32)ulSourceReceived);
  1440.     if (m_pStats->m_pTotal) m_pStats->m_pTotal->SetInt((INT32)ulSourceTotal);
  1441.     if (m_pStats->m_pClipBandwidth) m_pStats->m_pClipBandwidth->SetInt((INT32)ulSourceBandwidth);
  1442.     if (m_pStats->m_pLost) m_pStats->m_pLost->SetInt((INT32)ulSourceLost);    
  1443.     if (m_pStats->m_pCurBandwidth) m_pStats->m_pCurBandwidth->SetInt((INT32)ulSourceBandwidth);
  1444.     if (m_pStats->m_pAvgBandwidth) m_pStats->m_pAvgBandwidth->SetInt((INT32)ulSourceBandwidth);
  1445.     // update buffering mode(local machine)
  1446.     if (m_pStats->m_pBufferingMode)
  1447.     {
  1448. m_pStats->m_pBufferingMode->SetInt(NORMAL_PLAY);
  1449.     }
  1450. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  1451.     
  1452.     return HXR_OK;
  1453. }
  1454. HX_RESULT
  1455. HXFileSource::_ProcessIdle(BOOL atInterrupt)
  1456. {
  1457.     HX_RESULT theErr = HXR_OK;
  1458.     if (m_bLocked)
  1459.     {
  1460. return HXR_OK;
  1461.     }
  1462.     theErr = _ProcessIdleExt(atInterrupt);
  1463.     if (HXR_ABORT == theErr)
  1464.     {
  1465. return HXR_OK;
  1466.     }
  1467.     // need to try the next fileformat for same mimetype...
  1468.     // cannot do it at interrupt time!
  1469.     if (m_pCurrentFileFormatUnk && 
  1470. (m_bCurrentFileFormatUnkInUse || atInterrupt))
  1471.     {
  1472. return HXR_OK;
  1473.     }
  1474.     m_bLocked = TRUE;
  1475.     if (m_pCurrentFileFormatUnk)
  1476.     {
  1477. m_bCurrentFileFormatUnkInUse = TRUE;
  1478. CleanupFileObjects();
  1479. ReSetup();
  1480. m_bLocked = FALSE;
  1481. return HXR_OK;
  1482.     }
  1483.     if (!m_bInitialized)
  1484.     {
  1485.         m_bLocked = FALSE;
  1486.         return theErr;
  1487.     }
  1488.     if (m_bRedirectPending && !m_bPartOfNextGroup)
  1489.     {
  1490.         m_bRedirectPending = FALSE;
  1491.         HX_ASSERT(m_pRedirectURL);
  1492. theErr = m_pSourceInfo->HandleRedirectRequest((char*)m_pRedirectURL->GetURL());
  1493.         HX_DELETE(m_pRedirectURL);
  1494.         m_bLocked = FALSE;
  1495.         return theErr;
  1496.     }
  1497.     // we keep RAM FF object around by AddRef() in ::InitFileFormat
  1498.     // to avoid self-destruct in ::InitDone when it's not a RAM 
  1499.     HX_RELEASE(m_pRAMFFObject);
  1500.     if (!m_bSourceEnd && !m_bFirstResume)
  1501.     {
  1502. theErr = FillBuffers();
  1503. if (theErr == HXR_AT_END)
  1504. {
  1505.     SetEndOfClip();
  1506.     theErr = HXR_OK;
  1507. }
  1508.     }
  1509.     if (!theErr)
  1510.     {
  1511. UINT32 ulCurrentTime = m_pPlayer->GetInternalCurrentPlayTime();
  1512. // set m_bDelayed to FALSE as soon as it's due to begin playback
  1513. // even it's still in pre-fetch mode
  1514. if (!m_bPaused && m_bDelayed)
  1515. {
  1516.     UINT32 ulStartTime = 0;
  1517.     if (m_ulDelay > m_ulPreRollInMs + NETWORK_FUDGE_FACTOR)
  1518.     {
  1519. ulStartTime = m_ulDelay - (m_ulPreRollInMs + NETWORK_FUDGE_FACTOR);
  1520.     }
  1521.   
  1522.     if (ulCurrentTime >= ulStartTime)
  1523.          {
  1524. m_bDelayed = FALSE;
  1525.     }
  1526. }
  1527. if  (!m_bSourceEnd && m_bIsPreBufferingStarted && !m_bIsPreBufferingDone)
  1528. {
  1529.     /* Get Current buffering status every 1 sec. */
  1530.     UINT32 ulCurrentSystemTime = HX_GET_TICKCOUNT();
  1531.     if (CALCULATE_ELAPSED_TICKS(m_ulLastBufferingCalcTime, 
  1532. ulCurrentSystemTime) > 1000)
  1533.     {
  1534. m_ulLastBufferingCalcTime = ulCurrentSystemTime;
  1535. CalculateCurrentBuffering();
  1536.     }
  1537. }
  1538. // XXX HP TBD HTTP prefetch
  1539. // no prefetch support for now
  1540. if (m_bPrefetch)
  1541. {
  1542.     LeavePrefetch();
  1543. }
  1544. // rebuffer if the source hasn't satisfy its initial preroll when it's 
  1545. // time to start
  1546. // resume in InitialBufferingDone()
  1547. if (m_pPlayer->IsPlaying()  &&
  1548.     !m_bPartOfPrefetchGroup &&
  1549.     m_bInitialBuffering     && 
  1550.     !m_bRebufferingRequired &&
  1551.     (ulCurrentTime + MIN_BUFFERTIME_BEFORE_DELAY) >= m_ulDelay)
  1552. {
  1553.          DoRebuffer();
  1554. }
  1555.     }
  1556.     m_bLocked = FALSE;
  1557.     if (!theErr && !m_bIsActive && !m_bDelayed &&
  1558. m_pPlayer->GetInternalCurrentPlayTime() >= m_ulDelay)
  1559.     {
  1560. AdjustClipBandwidthStats(TRUE);
  1561.     }
  1562.     /* tell the player about the error...
  1563.      * This is crucial...
  1564.      */
  1565.     if (theErr)
  1566.     {
  1567. ReportError(theErr);
  1568.     }
  1569.     return theErr;
  1570. }
  1571. HX_RESULT
  1572. HXFileSource::_ProcessIdleExt(BOOL atInterrupt)
  1573. {
  1574.     return HXR_OK;
  1575. }
  1576. STDMETHODIMP
  1577. HXFileSource::InitDone
  1578. (
  1579.     HX_RESULT status
  1580. )
  1581. {
  1582.     if (!m_bValidateMetaDone)
  1583.     {
  1584. m_bValidateMetaDone = TRUE;
  1585. if (HXR_OK == status)
  1586. {
  1587.     m_bIsMeta = TRUE;
  1588.     // reset all the timing attributes since meta file(RAM)
  1589.     // doesn't support any
  1590.     SetPlayTimes(0, 0, 0, 0);
  1591. }
  1592. else
  1593. {
  1594.     m_bIsMeta = FALSE;
  1595.     HX_RELEASE(m_pFFObject);
  1596.     HX_RELEASE(m_pCurrentFileFormatUnk);
  1597.     HX_RELEASE(m_pFileFormatEnumerator);
  1598.     
  1599.     // not a meta file, since the file object has been initialized,
  1600.     // calling ExtendedSetup() again to find the actual mimetype if
  1601.     // the file object supports findings of mimetypes.
  1602.     return ExtendedSetup(m_pszURL);
  1603. }
  1604.     }
  1605.     if (!mLastError && status != HXR_OK)
  1606.     {
  1607. CheckForDefaultUpgrade(status);
  1608. /* do we need to try the next one! */
  1609. if (!m_pCurrentFileFormatUnk && m_pFileFormatEnumerator)
  1610. {
  1611.     m_pFileFormatEnumerator->GetNextPlugin(m_pCurrentFileFormatUnk, NULL);
  1612.     if (m_pCurrentFileFormatUnk && m_pSourceInfo)
  1613.     {
  1614. m_pSourceInfo->ScheduleProcessCallback();
  1615.     }
  1616. }
  1617. // early exit to try next fileformat for the same mimetype!
  1618. if (m_pCurrentFileFormatUnk)
  1619. {
  1620.     return HXR_OK;
  1621. }
  1622. mLastError = status;
  1623. // merge any upgrade requests for this source to the player
  1624. MergeUpgradeRequest(m_bAddDefaultUpgrade, m_pDefaultUpgradeString);
  1625.     }
  1626.     if (HXR_OK == status && m_ulStreamHeadersExpected == 0)
  1627.     {
  1628. HX_RELEASE(m_pBackChannel);
  1629. HX_RELEASE(m_pASMSource);
  1630. m_pFFObject->QueryInterface(IID_IHXBackChannel, (void**) &m_pBackChannel);
  1631. m_pFFObject->QueryInterface(IID_IHXASMSource, (void**) &m_pASMSource);
  1632. HX_RESULT result = m_pFFObject->GetFileHeader();
  1633.      return result;
  1634.     }
  1635.     else 
  1636.     {
  1637. ReportError(status);
  1638.     }
  1639.     return HXR_OK;
  1640. }
  1641. STDMETHODIMP
  1642. HXFileSource::FileHeaderReady
  1643. (
  1644.     HX_RESULT     status,
  1645.     IHXValues*     pHeader
  1646. )
  1647. {
  1648.     HX_RELEASE(m_pFileHeader);
  1649.     if (HXR_OK == status)
  1650.     {
  1651. status = HandleSDPData(pHeader);
  1652.     }
  1653. #if defined(HELIX_FEATURE_RECORDCONTROL)
  1654.     SendHeaderToRecordControl(TRUE, pHeader);
  1655. #endif /* HELIX_FEATURE_RECORDCONTROL */
  1656.     return ContinueWithFileHeader(status, pHeader);
  1657. }
  1658. HX_RESULT
  1659. HXFileSource::ContinueWithFileHeader(HX_RESULT status, IHXValues* pHeader)
  1660. {
  1661.     HX_RESULT      result = HXR_OK;
  1662.     HX_ASSERT(!m_pFileHeader);
  1663.     if( pHeader )
  1664.     {
  1665. m_pFileHeader = pHeader;
  1666. m_pFileHeader->AddRef();
  1667.     }
  1668.     result = ContinueWithFileHeaderExt(status, m_pFileHeader);
  1669.     if (result == HXR_REQUEST_UPGRADE)
  1670.     {
  1671. mLastError = result;
  1672. return HXR_OK;
  1673.     }
  1674.     else if (result == HXR_WOULD_BLOCK)
  1675.     {
  1676. return HXR_OK;
  1677.     }
  1678.     m_bContinueWithHeaders = FALSE;
  1679.     if (status != HXR_OK)
  1680.     {
  1681. CheckForDefaultUpgrade(status);
  1682. /* do we need to try the next one! */
  1683. if (!m_pCurrentFileFormatUnk && m_pFileFormatEnumerator)
  1684. {
  1685.     m_pFileFormatEnumerator->GetNextPlugin(m_pCurrentFileFormatUnk, NULL);
  1686.     // only proceed source info(renderer) initialization in the 
  1687.     // CURRENT group so that sources in the NEXT group won't have
  1688.     // effect(i.e. layout) in the current playback
  1689.     if (m_pCurrentFileFormatUnk && 
  1690. m_pPlayer &&
  1691. m_pSourceInfo &&
  1692. m_pPlayer->GetCurrentGroupID() == m_pSourceInfo->m_uGroupID)
  1693.     {
  1694. m_pSourceInfo->ScheduleProcessCallback();
  1695.     }
  1696. }
  1697. // early exit to try next fileformat for the same mimetype!
  1698. if (m_pCurrentFileFormatUnk)
  1699. {
  1700.     return HXR_OK;
  1701. }
  1702.      mLastError = status;
  1703. // merge any upgrade requests for this source to the player
  1704. MergeUpgradeRequest(m_bAddDefaultUpgrade, m_pDefaultUpgradeString);
  1705. ReportError(mLastError);
  1706. return HXR_FAILED;
  1707.     }
  1708.     ProcessFileHeader();
  1709.     if( m_pFileHeader )
  1710.     {
  1711. UINT32 ulLiveStream = 0;
  1712. m_pFileHeader->GetPropertyULONG32("LiveStream", ulLiveStream);
  1713. mLiveStream = ulLiveStream ? TRUE : FALSE;
  1714. ULONG32 ulFlags = 0;
  1715. m_pFileHeader->GetPropertyULONG32("Flags", ulFlags);
  1716. mSaveAsAllowed = ulFlags & HX_SAVE_ENABLED ? TRUE : FALSE;
  1717. for (UINT16 i=0; (result == HXR_OK) && i < m_ulStreamHeadersExpected; i++)
  1718. {
  1719.     result = m_pFFObject->GetStreamHeader(i);
  1720. }
  1721.     }
  1722.     return result;
  1723. }
  1724. HX_RESULT
  1725. HXFileSource::ContinueWithFileHeaderExt(HX_RESULT status, IHXValues* pHeader)
  1726. {
  1727.     return HXR_OK;
  1728. }
  1729. STDMETHODIMP
  1730. HXFileSource::StreamHeaderReady(HX_RESULT status, IHXValues* pHeader)
  1731. {
  1732.     HX_RESULT     theErr = HXR_OK;
  1733.     char     szRegKeyName[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
  1734.     IHXBuffer*     pszParentName = NULL;
  1735.     STREAM_INFO*    pStreamInfo = NULL;
  1736.     // we do not support receiving headers once we have started getting data...
  1737.     if (m_bReceivedData)
  1738. return HXR_FAILED; // define some more appropriate error code..
  1739.     if (HXR_OK == status)
  1740.     {
  1741. status = HandleSDPData(pHeader);
  1742.     }
  1743.     if (HXR_OK != status)
  1744.     {
  1745. mLastError = status;
  1746.      ReportError(mLastError);
  1747. return HXR_OK;
  1748.     }
  1749. #if defined(HELIX_FEATURE_RECORDCONTROL)
  1750.     SendHeaderToRecordControl(FALSE, pHeader);
  1751. #endif /* HELIX_FEATURE_RECORDCONTROL */
  1752.     StreamHeaderReadyExt(pHeader);
  1753.     // fileformat initialized...clear any pending upgrade requests for this source!
  1754.     ClearUpgradeRequest();
  1755.     // we have already received enough headers...
  1756.     if (m_uNumStreams >= m_ulStreamHeadersExpected)
  1757. return HXR_FAILED;
  1758.     theErr = ProcessStreamHeaders(pHeader, pStreamInfo);
  1759.     if (!theErr)
  1760.     {
  1761. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  1762.         HX_ASSERT(pStreamInfo);
  1763. // create all the statistic registry keys
  1764. if (m_pRegistry && m_pStats &&
  1765.     HXR_OK == m_pRegistry->GetPropName(m_pStats->m_ulRegistryID, pszParentName))
  1766. {
  1767.     SafeSprintf(szRegKeyName, MAX_DISPLAY_NAME, "%s.Stream%ld", pszParentName->GetBuffer(), 
  1768. m_ulStreamIndex);
  1769.     /* does this ID already exists ? */
  1770.     UINT32 ulRegistryID = m_pRegistry->GetId(szRegKeyName);
  1771.     if (!ulRegistryID)
  1772.     {
  1773. ulRegistryID = m_pRegistry->AddComp(szRegKeyName);
  1774.     }
  1775.     pStreamInfo->m_pStats = new STREAM_STATS(m_pRegistry, ulRegistryID);
  1776.             if(pStreamInfo->m_pStats)
  1777.             {
  1778.         // set stream bandwidth
  1779.         pStreamInfo->m_pStats->m_pClipBandwidth->SetInt((INT32)pStreamInfo->BufferingState().AvgBandwidth());
  1780.             }
  1781.             else
  1782.             {
  1783.                 // NOTE: It may be that we can still function without the 
  1784.                 // m_pStats object, but can we still function if we are 
  1785.                 // running out of memory at this point? Assuming no.
  1786.                 theErr = HXR_OUTOFMEMORY;
  1787.             }
  1788. }
  1789. HX_RELEASE(pszParentName);
  1790. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  1791.         m_ulStreamIndex++;
  1792.         m_uNumStreams++;
  1793.     }
  1794.     if (!theErr && m_uNumStreams == m_ulStreamHeadersExpected)
  1795.     {
  1796. m_uActiveStreams = m_uNumStreams;
  1797. m_ulOriginalDuration = m_ulDuration;
  1798. m_bInitialized     = TRUE;
  1799. theErr = AdjustClipTime();
  1800. m_pBufferManager->Init();
  1801.     }
  1802.     return theErr;
  1803. }
  1804. HX_RESULT
  1805. HXFileSource::StreamHeaderReadyExt(IHXValues* pHeader)
  1806. {
  1807.     return HXR_OK;
  1808. }
  1809. STDMETHODIMP
  1810. HXFileSource::PacketReady(HX_RESULT status, IHXPacket* pPacket)
  1811. {
  1812.     HX_RESULT theErr = HXR_OK;
  1813.     // We should have been initialized by now
  1814.     HX_ASSERT(m_bInitialized);
  1815.     if (!m_bInitialized)
  1816.     {
  1817. return HXR_NOT_INITIALIZED;
  1818.     }
  1819.     
  1820.     // Report a non-HXR_OK error code only if no packet. If a packet
  1821.     // accompanies the error code we assume end of stream and handle
  1822.     // later on (see below).
  1823.     if (!pPacket)
  1824.     {
  1825.         if (HXR_OK != status)
  1826.         {
  1827.     mLastError = status;
  1828.     ReportError(mLastError);
  1829.             return HXR_OK;
  1830.         }
  1831.         else
  1832.         {
  1833.     // HXR_OK with a NULL packet makes no sense
  1834.     return HXR_INVALID_PARAMETER;
  1835.         }
  1836.     }
  1837.     
  1838.     IHXBuffer*     pBuffer     = 0;
  1839.     UINT32     ulPacketTime    = 0;     // packet time encoded
  1840.     UINT32     ulPacketFilledDuration = 0;     // packets' time have been filled 
  1841.     UINT32      ulEventBeginTime = 0;     // start pos of the packet(event) 
  1842.     INT64     llActualPacketTime = 0;     // packet time with timestamp rollover
  1843.     INT64     llActualEventBeginTime = 0;     // start pos of the packet(event) with timestamp rollover
  1844.     ULONG32     ulFlags     = 0;
  1845.     UINT16     uStreamNumber   = 0;
  1846.     UINT8     unASMFlags     = 0;
  1847.     UINT16     unASMRuleNumber = 0;
  1848.     UINT32     streamPreRoll   = 0;
  1849.     UINT32     ulMinimumTotalPreroll = 0;
  1850.     if (HXR_OK != pPacket->Get(pBuffer, ulPacketTime, uStreamNumber, unASMFlags, unASMRuleNumber))
  1851.     {
  1852. theErr = HXR_FAILED;
  1853. return theErr;
  1854.     }
  1855. #if defined(_DEBUG) && defined(DEBUG_LOG_INFO)
  1856.     HXStaticStatLog::StatPrintf("Packet: StreamNumber: %u TimeStamp: %lun", uStreamNumber, ulPacketTime);
  1857. #endif
  1858.     HX_RELEASE(pBuffer);
  1859.     CHXEvent*     theEvent     = NULL;
  1860.     STREAM_INFO*    lpStreamInfo    = NULL;
  1861.     CHXEventList*  lEventList     = NULL;
  1862.     if (!mStreamInfoTable->Lookup((LONG32) uStreamNumber, (void *&) lpStreamInfo))
  1863.     {
  1864. return HXR_INVALID_PARAMETER;
  1865.     }
  1866.     if (status != HXR_OK)
  1867.     {
  1868. if (!lpStreamInfo->m_bSrcStreamDone)
  1869. {
  1870.     // if the status is not OK, it is probably the end of the stream..
  1871.     // we should mark this stream as DONE...
  1872.     lpStreamInfo->m_bPacketRequested     = FALSE;
  1873.     lpStreamInfo->m_bSrcStreamFillingDone   = TRUE;
  1874.     lpStreamInfo->m_bSrcStreamDone     = TRUE;
  1875.     if (m_uNumStreamsToBeFilled > 0)
  1876.     {
  1877. m_uNumStreamsToBeFilled--;
  1878.     }
  1879.     
  1880.     if (m_uActiveStreams > 0)
  1881.     {
  1882. m_uActiveStreams--;
  1883.     }
  1884.     
  1885.     if (m_uActiveStreams == 0)
  1886.     {
  1887. SetEndOfClip();
  1888.     }
  1889. }
  1890. return HXR_OK;
  1891.     }
  1892.     lpStreamInfo->m_ulReceived++;
  1893.     if (!theErr)
  1894.     {
  1895. // reset
  1896. lpStreamInfo->m_bPacketRequested    = FALSE;
  1897. lEventList = &lpStreamInfo->m_EventList;
  1898.     }
  1899.     /*
  1900.      * Save off the initial timestamp for live streams so we can buffer
  1901.      * relative to the first timstamp
  1902.      */
  1903.     if (m_bInitialPacket)
  1904.     {
  1905. m_bInitialPacket = FALSE;
  1906. m_ulFirstPacketTime = ulPacketTime;
  1907.     }
  1908.     // This is the time according to the stream...
  1909.     llActualPacketTime = 
  1910. lpStreamInfo->BufferingState().CreateINT64Timestamp(ulPacketTime);
  1911.     llActualEventBeginTime = llActualPacketTime + m_ulDelay;
  1912.     /* subtract start time from player time */
  1913.     if (m_ulStartTime > 0)
  1914.     {
  1915. if (m_ulStartTime < llActualPacketTime) 
  1916. {
  1917.     llActualPacketTime -= m_ulStartTime; 
  1918. }
  1919. else
  1920. {
  1921.     llActualPacketTime = 0;
  1922. }
  1923. if (m_ulStartTime < llActualEventBeginTime) 
  1924. {
  1925.     llActualEventBeginTime -= m_ulStartTime; 
  1926. }
  1927. else
  1928. {
  1929.     llActualEventBeginTime = 0;
  1930. }
  1931.     }
  1932.     
  1933.     HX_ASSERT(llActualEventBeginTime < MAX_UINT32);
  1934.     HX_ASSERT(llActualPacketTime < MAX_UINT32);
  1935.     ulEventBeginTime = INT64_TO_UINT32(llActualEventBeginTime);
  1936.     ulPacketFilledDuration = INT64_TO_UINT32(llActualPacketTime);
  1937. #if defined(HELIX_FEATURE_RECORDCONTROL)
  1938.     if (m_pRecordControl)
  1939.     {
  1940. m_pRecordControl->OnPacket(pPacket, m_ulStartTime - m_ulDelay);
  1941.     }
  1942. #endif /* HELIX_FEATURE_RECORDCONTROL */
  1943.     if (!m_bPlayFromRecordControl)
  1944.     {
  1945. /* 
  1946.  * force a minimum preroll of 1 second to ensure that we deliver
  1947.  * packet in time to the renderers. e.g. with delayed RealText
  1948.  * with a preroll of 0 and delay of 10 seconds, it is 
  1949.  * possible to send packets at time 0 AFTER 10 seconds if we 
  1950.  * do not ensure this minimum preroll
  1951.  * helps in fixing random "realtext not displaying" bug
  1952.  */
  1953.         streamPreRoll = max(lpStreamInfo->BufferingState().GetMinPrerollInMs(),1000);
  1954. ulEventBeginTime = (ulEventBeginTime > streamPreRoll) ? (ulEventBeginTime - streamPreRoll) : 0;
  1955. theEvent = new CHXEvent(pPacket, ulEventBeginTime);
  1956. if(!theEvent) 
  1957. {
  1958.     theErr = HXR_OUTOFMEMORY;
  1959. }
  1960. // enqueue the event into event queue
  1961. if(!theErr) 
  1962. {
  1963.          /* offset used by Player::ProcessCurrentEvents to send to renderer::OnPacket */
  1964.          theEvent->SetTimeOffset(m_ulStartTime - m_ulDelay); 
  1965.     theErr = lEventList->InsertEvent(theEvent);
  1966. }
  1967. if (!theErr)
  1968. {
  1969.     m_pBufferManager->UpdateCounters(pPacket);
  1970. }
  1971.     }
  1972.     m_llLastFillEndTime = llActualPacketTime;
  1973.     if (m_bInFillMode)
  1974.     {
  1975. UINT32 ulDuration = 0;
  1976. UINT32 ulRemainToBufferInMs = 0;
  1977. UINT32 ulRemainToBuffer = 0;
  1978. m_pBufferManager->GetRemainToBuffer(ulRemainToBufferInMs,
  1979.     ulRemainToBuffer);
  1980. /* Logic:
  1981.     In FillBuffers(), we ask for a packet for a particular stream. If
  1982.     the fileformat does not return the packet immediately (i.e. we 
  1983.     go again to ask for the packet from the same stream but find out that
  1984.     we had already asked for it earlier and have not yet received it,
  1985.     the streamFilling is marked as done for that fillbuffer() iteration.
  1986.     In the meantime, we keep on asking for the packets from other streams
  1987.     In meanwhile, if the fileformat returns a packet for the stream marked 
  1988.     as done earlier, we re-activate that stream if the time of the packet
  1989.     is less than the time we fill all streams up to.
  1990.  */
  1991. if (lpStreamInfo->m_bSrcStreamFillingDone &&
  1992.     (ulRemainToBufferInMs > 0 || ulRemainToBuffer > 0) &&
  1993.     ulPacketFilledDuration <= lpStreamInfo->m_ulDuration &&
  1994.     !lpStreamInfo->m_bSrcStreamDone)
  1995. {
  1996.     lpStreamInfo->m_bSrcStreamFillingDone = FALSE;
  1997.          m_uNumStreamsToBeFilled++;
  1998. }
  1999. if (!lpStreamInfo->m_bSrcStreamDone && 
  2000.     !lpStreamInfo->m_bSrcStreamFillingDone &&
  2001.     m_uNumStreamsToBeFilled > 0)
  2002. {
  2003.             /* When playing from Record Control buffering can happen after seek to 
  2004.                a cached position. In this case we dont need to accelerate packet 
  2005.                retriaval and can stop filling the stream.
  2006.              */
  2007.     if (ulPacketFilledDuration > lpStreamInfo->m_ulDuration ||
  2008. (ulRemainToBufferInMs == 0 && ulRemainToBuffer == 0) ||
  2009.                 (m_bPlayFromRecordControl && ulPacketFilledDuration >= m_pPlayer->GetInternalCurrentPlayTime() + ulRemainToBufferInMs))
  2010.     {
  2011. // this value also updated in PacketReady()
  2012. lpStreamInfo->m_bSrcStreamFillingDone  = TRUE;
  2013. if (m_uNumStreamsToBeFilled > 0)
  2014. {
  2015.     m_uNumStreamsToBeFilled--;
  2016. }
  2017.     }
  2018. }
  2019.     }
  2020.     if (!theErr)
  2021.     {
  2022. m_bReceivedData     = TRUE;
  2023.     }
  2024.     else if (theEvent)
  2025.     {
  2026.         HX_DELETE(theEvent);
  2027.     }
  2028.     return theErr;
  2029. }
  2030. STDMETHODIMP
  2031. HXFileSource::StreamDone(UINT16   uStreamNumber)
  2032. {
  2033.     STREAM_INFO    *lpStreamInfo    = NULL;
  2034.     if (!mStreamInfoTable->Lookup((LONG32) uStreamNumber, (void *&) lpStreamInfo))
  2035.     {
  2036. return HXR_INVALID_PARAMETER;
  2037.     }
  2038.     if (!lpStreamInfo->m_bSrcStreamDone)
  2039.     {
  2040. lpStreamInfo->m_bSrcStreamDone = TRUE;
  2041. lpStreamInfo->m_bSrcStreamFillingDone = TRUE;
  2042. lpStreamInfo->m_bPacketRequested = FALSE;
  2043. if (m_uNumStreamsToBeFilled > 0)
  2044. {
  2045.     m_uNumStreamsToBeFilled--;
  2046. }
  2047. if (m_uActiveStreams > 0)
  2048. {
  2049.     m_uActiveStreams--;
  2050. }
  2051.     
  2052. if (m_uActiveStreams == 0)
  2053. {
  2054.     SetEndOfClip();
  2055. }
  2056.     }
  2057.     return HXR_OK;
  2058. }
  2059. STDMETHODIMP
  2060. HXFileSource::SeekDone(HX_RESULT status)
  2061. {
  2062.     HX_RESULT lResult = HXR_OK;
  2063.     
  2064.     if (m_nSeeking > 0)
  2065.     {
  2066. m_nSeeking--;
  2067.     }
  2068.     _ProcessIdle(FALSE);
  2069.     return lResult;
  2070. }
  2071. STDMETHODIMP HXFileSource::RedirectDone(IHXBuffer* pURL)
  2072. {
  2073.     HX_RESULT hr = HXR_NOTIMPL;
  2074.     // handle redirect to diff. protocol from HTTP file system
  2075.     if (m_pszURL && pURL)
  2076.     {
  2077. if (strncasecmp(m_pszURL, "http://", 7) == 0 &&
  2078.     strncasecmp((const char*)pURL->GetBuffer(), "http://", 7) != 0)
  2079. {
  2080.             if (m_bPartOfNextGroup)
  2081.             {
  2082.                 m_bRedirectPending = TRUE;
  2083.                 HX_DELETE(m_pRedirectURL);
  2084.                 m_pRedirectURL = new CHXURL((const char*)pURL->GetBuffer());
  2085.             }
  2086.             else
  2087.             {
  2088.           hr = m_pSourceInfo->HandleRedirectRequest((char*)pURL->GetBuffer());
  2089.             }
  2090. }
  2091.     }
  2092.     
  2093.     return hr;
  2094. }
  2095. // routine to read from the file to keep all streams filled to their preroll value
  2096. HX_RESULT    
  2097. HXFileSource::FillBuffers(void)
  2098. {
  2099.     /* 
  2100.      * Do not call GetPacket if we have not yet received SeekDone from
  2101.      * the file format plugin.
  2102.      *     || 
  2103.      * We are in a paused state and no rebuffering and no fast start 
  2104.      * is required.
  2105.      *     ||
  2106.      * We are in force end mode such as seeking to the end of the source duration
  2107.      */
  2108.     if (m_nSeeking > 0 ||
  2109. (m_bPaused && !m_bFastStartInProgress && !m_bRebufferingRequired && !m_pRecordControl) ||
  2110. m_bForcedSourceEnd)
  2111.     {
  2112. return HXR_OK;
  2113.     }
  2114.     HX_RESULT theErr = HXR_OK;
  2115.     UINT32 ulRemainToBufferInMs = 0; 
  2116.     UINT32 ulRemainToBuffer = 0;
  2117.     UINT32 lPlayPos = m_pPlayer->GetInternalCurrentPlayTime();
  2118.     UINT32 ulCurrentTime = HX_GET_TICKCOUNT();
  2119.     m_uNumStreamsToBeFilled = 0;
  2120.     m_ulMaxPreRoll = 0;
  2121.   
  2122.     CHXMapLongToObj::Iterator ndxStream = mStreamInfoTable->Begin();
  2123.     STREAM_INFO* lpStreamInfo    = NULL;
  2124.     m_pBufferManager->GetMaximumPreroll(m_ulMaxPreRoll);
  2125.     m_pBufferManager->GetRemainToBuffer(ulRemainToBufferInMs,
  2126. ulRemainToBuffer);
  2127.     for(; ndxStream != mStreamInfoTable->End(); ++ndxStream)
  2128.     {
  2129. lpStreamInfo = (STREAM_INFO*) (*ndxStream);
  2130. if(!lpStreamInfo->m_bSrcStreamDone)
  2131. {
  2132.     m_uNumStreamsToBeFilled++;
  2133.     lpStreamInfo->m_bSrcStreamFillingDone = FALSE;
  2134. }
  2135.     }
  2136.     /*
  2137.      * The fill end time must be offset by the intial timestamp if this
  2138.      * is a live stream which is saved in the initial PacketReady
  2139.      */
  2140.     // we will always attempt to have m_MaxPreRoll time of data in the audio and video event queues
  2141.     m_llFillEndTime = CAST_TO_INT64 (lPlayPos + 
  2142.       m_ulMaxPreRoll + m_pPlayer->m_ulMinimumAudioPreroll + 
  2143.       m_pPlayer->GetGranularity());
  2144.     if (!m_pRecordControl &&
  2145. !m_bRebufferingRequired &&
  2146. ulRemainToBufferInMs == 0 &&
  2147. ulRemainToBuffer == 0 && 
  2148. m_llFillEndTime <= m_llLastFillEndTime)
  2149.     {
  2150. return HXR_OK;
  2151.     }
  2152. #if defined(HELIX_FEATURE_RECORDCONTROL)
  2153.     if (m_pRecordControl && !m_pRecordControl->CanAcceptPackets())
  2154.     {
  2155. return HXR_OK;
  2156.     }
  2157. #endif /* HELIX_FEATURE_RECORDCONTROL */
  2158.     m_bInFillMode   = TRUE;
  2159.     while(!theErr && m_uNumStreamsToBeFilled > 0)
  2160.     {
  2161. ndxStream = mStreamInfoTable->Begin();
  2162. for (; !theErr && ndxStream != mStreamInfoTable->End(); ++ndxStream)
  2163. {
  2164.     lpStreamInfo    = (STREAM_INFO*) (*ndxStream);
  2165.     if (!lpStreamInfo->m_bSrcStreamDone && 
  2166. !lpStreamInfo->m_bSrcStreamFillingDone && 
  2167. !lpStreamInfo->m_bPacketRequested)
  2168.     {
  2169. // this will be reset in PacketReady()
  2170. lpStreamInfo->m_bPacketRequested    = TRUE;
  2171.                 HX_RESULT retVal = m_pFFObject->GetPacket((UINT16) lpStreamInfo->m_uStreamNumber);
  2172. if (HXR_OK != retVal )
  2173. {
  2174.                     StreamDone(lpStreamInfo->m_uStreamNumber);
  2175.                     // Don't lose OOM errors.
  2176.                     if( retVal == HXR_OUTOFMEMORY )
  2177.                     {
  2178.                         theErr = retVal;
  2179.                     }
  2180. }
  2181.     } 
  2182.     else if (lpStreamInfo->m_bPacketRequested)
  2183.     {
  2184. /* This logic applies to only single threaded application
  2185.  * where if we request a packet, we are either gonna get it 
  2186.  * immediately or not get it at all till a later time--
  2187.  * GetPacket() to ff->read to fs->readdone to ff->
  2188.  * packetready to fileresponse(this) 
  2189.  * In this case, m_uNumStreamsToBeFilled
  2190.  * will be adjusted in packetready depending on timestamp of stream
  2191.  * and where we wanna fill that stream upto
  2192.  * If packet requested is TRUE, it means fileformat did not response
  2193.  * immediately and thus one less stream is to be filled.
  2194.  * This however may not work in multi-threaded case where
  2195.  * fileplugin can send a response at any time.
  2196.  */
  2197. if (!lpStreamInfo->m_bSrcStreamFillingDone)
  2198. {
  2199.     lpStreamInfo->m_bSrcStreamFillingDone = TRUE;
  2200.     if (m_uNumStreamsToBeFilled > 0)
  2201.       {
  2202.      m_uNumStreamsToBeFilled--;
  2203.     }
  2204. }
  2205.     }
  2206. }
  2207.     }
  2208.     m_bInFillMode   = FALSE;
  2209.     return theErr;
  2210. }
  2211. void
  2212. HXFileSource::SetEndOfClip(BOOL bForcedEndofClip) 
  2213. {
  2214.     m_bForcedSourceEnd = bForcedEndofClip;
  2215.     if (!m_bSourceEnd)
  2216.     {
  2217. m_bSourceEnd = TRUE;   
  2218. m_pBufferManager->Stop();
  2219. m_pPlayer->EndOfSource(this);
  2220. #if defined(HELIX_FEATURE_RECORDCONTROL)
  2221. if (m_pRecordControl)
  2222. {
  2223.     m_pRecordControl->OnEndOfPackets();
  2224. }
  2225. #endif /* HELIX_FEATURE_RECORDCONTROL*/
  2226.     }
  2227. }
  2228. // IUnknown methods
  2229. /////////////////////////////////////////////////////////////////////////
  2230. // Method:
  2231. // IUnknown::QueryInterface
  2232. // Purpose:
  2233. // Implement this to export the interfaces supported by your 
  2234. // object.
  2235. //
  2236. STDMETHODIMP 
  2237. HXFileSource::CMimeFinderFileResponse::QueryInterface(REFIID riid, void** ppvObj)
  2238. {
  2239.     QInterfaceList qiList[] =
  2240.         {
  2241.             { GET_IIDHANDLE(IID_IHXFileMimeMapperResponse), (IHXFileMimeMapperResponse*)this },
  2242.             { GET_IIDHANDLE(IID_IHXFileRecognizerResponse), (IHXFileRecognizerResponse*)this },
  2243.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXFileMimeMapperResponse*)this },
  2244.         };
  2245.     
  2246.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  2247. }
  2248. /////////////////////////////////////////////////////////////////////////
  2249. // Method:
  2250. // IUnknown::AddRef
  2251. // Purpose:
  2252. // Everyone usually implements this the same... feel free to use
  2253. // this implementation.
  2254. //
  2255. STDMETHODIMP_(ULONG32) 
  2256. HXFileSource::CMimeFinderFileResponse::AddRef()
  2257. {
  2258.     return InterlockedIncrement(&m_lRefCount);
  2259. }
  2260. /////////////////////////////////////////////////////////////////////////
  2261. // Method:
  2262. // IUnknown::Release
  2263. // Purpose:
  2264. // Everyone usually implements this the same... feel free to use
  2265. // this implementation.
  2266. //
  2267. STDMETHODIMP_(ULONG32) 
  2268. HXFileSource::CMimeFinderFileResponse::Release()
  2269. {
  2270.     if (InterlockedDecrement(&m_lRefCount) > 0)
  2271.     {
  2272. return m_lRefCount;
  2273.     }
  2274.     delete this;
  2275.     return 0;
  2276. }
  2277. // IHXFileMimeMapperResponse methods
  2278. STDMETHODIMP 
  2279. HXFileSource::CMimeFinderFileResponse::MimeTypeFound(HX_RESULT status,
  2280.                                      const char* pMimeType)
  2281. {
  2282.     m_pSource->FinishSetup(status,pMimeType); 
  2283.     return HXR_OK; 
  2284. }
  2285. STDMETHODIMP 
  2286. HXFileSource::CMimeFinderFileResponse::GetMimeTypeDone(HX_RESULT status,
  2287.                                                        IHXBuffer* pMimeType)
  2288. {
  2289.     char* szMimeType = NULL;
  2290.     if (SUCCEEDED(status) && pMimeType)
  2291.     {
  2292.         pMimeType->AddRef();
  2293.         szMimeType = (char*)pMimeType->GetBuffer();
  2294.     }
  2295.     
  2296.     m_pSource->FinishSetup(status, szMimeType);
  2297.     HX_RELEASE(pMimeType);
  2298.     
  2299.     return HXR_OK;
  2300. }
  2301. /*
  2302.  * IHXRegistryID methods
  2303.  */
  2304. /************************************************************************
  2305.  * Method:
  2306.  *     IHXRegistryID::GetID
  2307.  * Purpose:
  2308.  *     Get registry ID(hash_key) of the objects(player, source and stream)
  2309.  *
  2310.  */
  2311. STDMETHODIMP 
  2312. HXFileSource::GetID(REF(UINT32) /*OUT*/ ulRegistryID)
  2313. {
  2314. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  2315.     (m_pStats)?(ulRegistryID = m_pStats->m_ulRegistryID):(ulRegistryID = 0);
  2316.    
  2317.     return HXR_OK;
  2318. #else
  2319.     return HXR_NOTIMPL;
  2320. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  2321. }
  2322. /************************************************************************
  2323.  * Method:
  2324.  *     IHXInfoLogger::LogInformation
  2325.  * Purpose:
  2326.  *     Logs any user defined information in form of action and 
  2327.  *     associated data.
  2328.  */
  2329. STDMETHODIMP
  2330. HXFileSource::LogInformation(const char* /*IN*/ pAction,
  2331.       const char* /*IN*/ pData)
  2332. {
  2333.     return HXR_OK;
  2334. }
  2335. BOOL
  2336. HXFileSource::IsSourceDone(void)
  2337. {
  2338.     return m_bSourceEnd;
  2339. }
  2340. STDMETHODIMP 
  2341. HXFileSource::GetCurrentBuffering (UINT16  uStreamNumber,
  2342.    REF(INT64)  llLowestTimestamp, 
  2343.    REF(INT64)  llHighestTimestamp,
  2344.    REF(UINT32) ulNumBytes,
  2345.    REF(BOOL)   bDone)
  2346. {
  2347.     llLowestTimestamp = 0; 
  2348.     llHighestTimestamp = 0;
  2349.     ulNumBytes = 0;
  2350.     bDone = FALSE;
  2351.     return HXR_OK;
  2352. }
  2353. void
  2354. HXFileSource::AdjustClipBandwidthStats(BOOL bActivate /* = FALSE */)
  2355. {
  2356.     m_bIsActive = bActivate;
  2357.     for (CHXMapLongToObj::Iterator i = mStreamInfoTable->Begin();
  2358.          i != mStreamInfoTable->End(); ++i) 
  2359.     {    
  2360. STREAM_INFO* pStreamInfo = (STREAM_INFO*) (*i);
  2361. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  2362. HX_ASSERT(pStreamInfo->m_pStats);
  2363. if (!pStreamInfo->m_pStats)
  2364. {
  2365.     continue;
  2366. }
  2367. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  2368. if (bActivate)
  2369. {
  2370.     pStreamInfo->BufferingState().SetAvgBWToASMBw();
  2371. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  2372.     pStreamInfo->m_pStats->m_pClipBandwidth->SetInt((INT32)pStreamInfo->BufferingState().AvgBandwidth());
  2373. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  2374. }
  2375. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  2376. else
  2377. {
  2378.     pStreamInfo->m_pStats->m_pClipBandwidth->SetInt(0);
  2379. }
  2380. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  2381.     }
  2382. }
  2383. BOOL
  2384. HXFileSource::CanBeResumed()
  2385. {
  2386.     BOOL    bResult = TRUE;
  2387.     UINT32  ulCurrentTime = 0;
  2388.     if (!m_bInitialized     ||
  2389. !m_pPlayer->IsInitialized() ||
  2390. m_bSourceEnd     ||
  2391. (m_pSourceInfo && !m_pSourceInfo->AreStreamsSetup()))
  2392.     {
  2393. bResult = FALSE;
  2394.     }
  2395.     else if (m_bPrefetch)
  2396.     {
  2397. HX_ASSERT(m_pSourceInfo?(m_pPlayer->GetCurrentGroupID() == m_pSourceInfo->m_uGroupID):TRUE);
  2398. ulCurrentTime = m_pPlayer->GetInternalCurrentPlayTime();
  2399. if (ulCurrentTime < m_ulPrefetchDelay)
  2400. {
  2401.     bResult = FALSE;
  2402. }
  2403.     }
  2404.     else if ((!m_bIsPreBufferingStarted && m_bDelayed) ||
  2405.      (m_bIsPreBufferingDone && ((!m_bPaused && !m_bFirstResume) || m_bDelayed)))
  2406.     {
  2407. bResult = FALSE;
  2408.     }
  2409.     return bResult;
  2410. }
  2411. #if defined(HELIX_FEATURE_ASM)
  2412. // SourceBandwidthInfo
  2413. STDMETHODIMP 
  2414. HXFileSource::SourceBandwidthInfo::QueryInterface(REFIID riid, void** ppvObj)
  2415. {
  2416.     QInterfaceList qiList[] =
  2417.         {
  2418.             { GET_IIDHANDLE(IID_IHXSourceBandwidthInfo), (IHXSourceBandwidthInfo*)this },
  2419.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXSourceBandwidthInfo*)this },
  2420.         };
  2421.     
  2422.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  2423. }
  2424. STDMETHODIMP_(ULONG32) 
  2425. HXFileSource::SourceBandwidthInfo::AddRef()
  2426. {
  2427.     return InterlockedIncrement(&m_lRefCount);
  2428. }
  2429. STDMETHODIMP_(ULONG32) 
  2430. HXFileSource::SourceBandwidthInfo::Release()
  2431. {
  2432.     if (InterlockedDecrement(&m_lRefCount) > 0)
  2433.     {
  2434. return m_lRefCount;
  2435.     }
  2436.     delete this;
  2437.     return 0;
  2438. }
  2439. STDMETHODIMP
  2440. HXFileSource::SourceBandwidthInfo::InitBw(IHXBandwidthManagerInput* pBwMgr)
  2441. {
  2442.     return HXR_OK;
  2443. }
  2444. STDMETHODIMP
  2445. HXFileSource::SourceBandwidthInfo::SetTransmitRate(UINT32 ulBitRate)
  2446. {
  2447.     return HXR_OK;
  2448. }
  2449. #endif /* HELIX_FEATURE_ASM */
  2450. void 
  2451. HXFileSource::CalculateCurrentBuffering(void)
  2452. {
  2453.     UINT32 ulRemainToBufferInMs = 0;
  2454.     UINT32 ulRemainToBuffer = 0;
  2455.     UINT32 ulExcessBufferInMs = 0;
  2456.     UINT32 ulExcessBuffer = 0;
  2457.     BOOL bValidInfo = FALSE;
  2458.     UINT32 ulActualExcessBufferInMs= 0;
  2459.     UINT32 ulActualExcessBuffer = 0;
  2460.     m_pBufferManager->GetExcessBufferInfo(ulRemainToBufferInMs,
  2461.   ulRemainToBuffer,
  2462.   ulExcessBufferInMs,
  2463.   ulExcessBuffer,
  2464.   bValidInfo,
  2465.      ulActualExcessBufferInMs,
  2466.      ulActualExcessBuffer);
  2467.     /* Be conservative in marking pre-buffering done */
  2468.     if (bValidInfo     &&
  2469. !m_bIsPreBufferingDone     &&
  2470. ulRemainToBufferInMs == 0   && 
  2471. ulRemainToBuffer == 0     && 
  2472. (ulExcessBuffer > m_ulAvgBandwidth/8 || 
  2473.  ulExcessBufferInMs > m_ulPreRollInMs))
  2474.     {
  2475. if (m_bDelayed && m_pPlayer)
  2476. {
  2477.     // pause the src if it's not time to play but it's done
  2478.     // with the pre-fetch
  2479.     if (m_pSourceInfo)
  2480.     {
  2481. m_pSourceInfo->UnRegister();
  2482.     }
  2483.     DoPause();
  2484. }
  2485. m_bIsPreBufferingDone = TRUE;
  2486.     }
  2487. }
  2488. void
  2489. HXFileSource::GetFileDone(HX_RESULT rc, IHXBuffer* pFile)
  2490. {
  2491.     HX_RESULT   ret = rc;
  2492.     UINT32      ulSDPBufferSize = 0;
  2493.     char*       pszSDPBuffer = NULL;
  2494.     CHXString   escapedSDP;
  2495.     CHXString   url;
  2496.     CHXBuffer*  pBuffer = NULL;
  2497.     if (HXR_OK != ret || !pFile)
  2498.     {
  2499.         goto cleanup;
  2500.     }
  2501.     ulSDPBufferSize = pFile->GetSize() + 1;
  2502.     pszSDPBuffer = new char[ulSDPBufferSize];
  2503.     if (NULL == pszSDPBuffer)
  2504.     {
  2505.         ret = HXR_OUTOFMEMORY;
  2506.         goto cleanup;
  2507.     }
  2508.     memset(pszSDPBuffer, 0, ulSDPBufferSize);
  2509.     strncpy(pszSDPBuffer, (const char*)pFile->GetBuffer(), pFile->GetSize());
  2510.     CHXURL::encodeURL(pszSDPBuffer, escapedSDP);
  2511.     url = HELIX_SDP_SCHEME;
  2512.     url += ":";
  2513.     url += escapedSDP;
  2514.     pBuffer = new CHXBuffer();
  2515.     if (NULL == pBuffer)
  2516.     {
  2517.         ret = HXR_OUTOFMEMORY;
  2518.         goto cleanup;
  2519.     }
  2520.     pBuffer->AddRef();
  2521.     pBuffer->Set((UCHAR*)(const char*)url, url.GetLength() + 1);
  2522.     ret = m_pSourceInfo->HandleRedirectRequest((char*)pBuffer->GetBuffer());
  2523. cleanup:
  2524.     HX_VECTOR_DELETE(pszSDPBuffer);
  2525.     HX_RELEASE(pBuffer);
  2526.     if (HXR_OK != ret)
  2527.     {
  2528. mLastError = ret;
  2529. ReportError(mLastError);
  2530.     }
  2531.     return;
  2532. }
  2533. void
  2534. HXFileSource::CheckForDefaultUpgrade(HX_RESULT status)
  2535. {
  2536. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  2537.     if (status == HXR_REQUEST_UPGRADE && !m_bAddDefaultUpgrade)
  2538.     {
  2539. m_bAddDefaultUpgrade = TRUE;
  2540. if (m_pMimeType && !(*m_pMimeType == '*'))
  2541. {
  2542.     m_pDefaultUpgradeString = ::new_string(m_pMimeType);
  2543. }
  2544. else if (m_pExtension)
  2545. {
  2546.     m_pDefaultUpgradeString = ::new_string(m_pExtension);
  2547. }
  2548.     }
  2549. #endif /* HELIX_FEATURE_AUTOUPGRADE */ 
  2550. }
  2551. UINT32 
  2552. HXFileSource::GetEventBeginTime(INT64 llPacketTime, UINT32 streamPreRoll)
  2553. {
  2554.     UINT32      ulEventBeginTime = 0;     // start pos of the packet(event) 
  2555.     INT64     llActualEventBeginTime = 0;     // start pos of the packet(event) with timestamp rollover
  2556.     UINT32     ulMinimumTotalPreroll = 0;
  2557.     // This is the time according to the stream...
  2558.     llActualEventBeginTime = llPacketTime + m_ulDelay;
  2559.     /* subtract start time from player time */
  2560.     if (m_ulStartTime > 0)
  2561.     {
  2562. if (m_ulStartTime < llActualEventBeginTime) 
  2563. {
  2564.     llActualEventBeginTime -= m_ulStartTime; 
  2565. }
  2566. else
  2567. {
  2568.     llActualEventBeginTime = 0;
  2569. }
  2570.     }
  2571.     
  2572.     HX_ASSERT(llActualEventBeginTime < MAX_UINT32);
  2573.     ulEventBeginTime = INT64_TO_UINT32(llActualEventBeginTime);
  2574.     ulEventBeginTime = (ulEventBeginTime > streamPreRoll) ? (ulEventBeginTime - streamPreRoll) : 0;
  2575.     return ulEventBeginTime;
  2576. }
  2577. HX_RESULT
  2578. HXFileSource::FillRecordControl()
  2579. {
  2580. #if defined(HELIX_FEATURE_RECORDCONTROL)
  2581.     if(!m_pRecordControl)
  2582. return HXR_FAILED; 
  2583.     FillBuffers();
  2584.     return HXR_OK;
  2585. #else
  2586.     return HXR_NOTIMPL;
  2587. #endif /* HELIX_FEATURE_RECORDCONTROL */
  2588. }
  2589. HX_RESULT HXFileSource::HandleSDPData(IHXValues* pHeader)
  2590. {
  2591.     HX_RESULT res = HXR_OK;
  2592.     IHXBuffer* pSDPDataBuf = NULL;
  2593.     if (!pHeader)
  2594.     {
  2595. HX_ASSERT(FALSE);
  2596. res = HX_INVALID_HEADER;
  2597.     }
  2598.     else if (HXR_OK == pHeader->GetPropertyCString("SDPData", pSDPDataBuf))
  2599.     {
  2600. IHXStreamDescription* pSD = 
  2601.     HXStreamDescriptionHelper::GetInstance((IHXClientEngine*)m_pEngine, 
  2602.    "application/sdp");
  2603. if (pSD)
  2604. {
  2605.     UINT16 nValues = 0;
  2606.     IHXValues** ppValues = NULL;
  2607.     res = pSD->GetValues(pSDPDataBuf, nValues, ppValues);
  2608.     if (HXR_OK == res)
  2609.     {
  2610. if (nValues >= 1)
  2611. {
  2612.     /* Merge headers from only the first header
  2613.      * since we aren't expecting 'm=' lines in the
  2614.      * SDP
  2615.      */
  2616.     CHXHeader::mergeHeaders(pHeader, ppValues[0]);
  2617. }
  2618. // Clean up the headers returned
  2619. for (UINT16 i = 0; i < nValues; i++)
  2620. {
  2621.     HX_RELEASE(ppValues[i]);
  2622. }
  2623. HX_VECTOR_DELETE(ppValues);
  2624.     }
  2625.     else if (HXR_OUTOFMEMORY != res)
  2626.     {
  2627. /* Mask any errors other than OUTOFMEMORY
  2628.  * because conversion of the SDPData field
  2629.  * is not critical
  2630.  */
  2631. res = HXR_OK;
  2632.     }
  2633.     HX_RELEASE(pSD);
  2634. }
  2635.     }
  2636.     HX_RELEASE(pSDPDataBuf);
  2637.     return res;
  2638. }
  2639. HXFileSource::CFileReader::CFileReader(HXFileSource* pOwner)
  2640.     : m_lRefCount(0),
  2641.       m_bGetFilePending(FALSE),
  2642.       m_pBuffer(NULL),
  2643.       m_pFile(NULL),
  2644.       m_pOwner(pOwner)
  2645. {
  2646. }
  2647. HXFileSource::CFileReader::~CFileReader()
  2648. {
  2649.     Close();
  2650. }
  2651. STDMETHODIMP HXFileSource::CFileReader::QueryInterface(REFIID riid, void** ppvObj)
  2652. {
  2653.     QInterfaceList qiList[] =
  2654.         {
  2655.             { GET_IIDHANDLE(IID_IHXFileResponse), (IHXFileResponse*)this },
  2656.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXFileResponse*)this },
  2657.         };
  2658.     
  2659.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  2660. }
  2661. STDMETHODIMP_(ULONG32) HXFileSource::CFileReader::AddRef()
  2662. {
  2663.     return InterlockedIncrement(&m_lRefCount);
  2664. }
  2665. STDMETHODIMP_(ULONG32) HXFileSource::CFileReader::Release()
  2666. {
  2667.     if (InterlockedDecrement(&m_lRefCount) > 0)
  2668.     {
  2669.         return m_lRefCount;
  2670.     }
  2671.     delete this;
  2672.     return 0;
  2673. }
  2674. STDMETHODIMP HXFileSource::CFileReader::InitDone(HX_RESULT status)
  2675. {
  2676.     HX_RESULT ret = HXR_FAIL;
  2677.     if (FAILED(status))
  2678.     {
  2679.         m_bGetFilePending = FALSE;
  2680.         m_pOwner->GetFileDone(HXR_FAILED, NULL);
  2681.     }
  2682.     else
  2683.     {
  2684. ret = m_pFile->Read(FILEREAD_SIZE);
  2685.     }
  2686.     return ret;
  2687. }
  2688. STDMETHODIMP HXFileSource::CFileReader::SeekDone(HX_RESULT /* status */)
  2689. {
  2690.     return HXR_OK;
  2691. }
  2692. STDMETHODIMP HXFileSource::CFileReader::ReadDone(HX_RESULT status,
  2693.          IHXBuffer* pBuffer)
  2694. {
  2695.     HX_RESULT   ret = status;
  2696.     IHXBuffer*  pMergedBuffer = NULL;
  2697.     if (SUCCEEDED(ret))
  2698.     {
  2699.         pMergedBuffer = new CHXBuffer();
  2700.         if (!pMergedBuffer)
  2701.         {
  2702.             ret = HXR_OUTOFMEMORY;
  2703.             goto cleanup;
  2704.         }
  2705.         pMergedBuffer->AddRef();
  2706.         if (!m_pBuffer)
  2707.         {
  2708.             pMergedBuffer->SetSize(pBuffer->GetSize());
  2709.             pMergedBuffer->Set(pBuffer->GetBuffer(), pBuffer->GetSize());
  2710.         }
  2711.         else
  2712.         {
  2713.             pMergedBuffer->SetSize(m_pBuffer->GetSize() + pBuffer->GetSize());
  2714.     memcpy(pMergedBuffer->GetBuffer(), m_pBuffer->GetBuffer(), m_pBuffer->GetSize()); /* Flawfinder: ignore */
  2715.     memcpy(pMergedBuffer->GetBuffer()+m_pBuffer->GetSize(), pBuffer->GetBuffer(), pBuffer->GetSize()); /* Flawfinder: ignore */
  2716. }
  2717. HX_RELEASE(m_pBuffer);
  2718. m_pBuffer = pMergedBuffer;
  2719. m_pFile->Read(FILEREAD_SIZE);
  2720.     }
  2721.     else
  2722.     {
  2723.         m_bGetFilePending = FALSE;
  2724. if (m_pBuffer && m_pBuffer->GetSize())
  2725. {     
  2726.             m_pOwner->GetFileDone(HXR_OK, m_pBuffer);
  2727. }
  2728. else
  2729. {     
  2730.     m_pFile->Seek(0, FALSE);
  2731.             m_pOwner->GetFileDone(HXR_FAILED, NULL);
  2732. }
  2733.     }
  2734. cleanup:
  2735.     return ret;
  2736. }
  2737. STDMETHODIMP HXFileSource::CFileReader::WriteDone(HX_RESULT /* status */)
  2738. {
  2739.     return HXR_OK;
  2740. }
  2741. STDMETHODIMP HXFileSource::CFileReader::CloseDone(HX_RESULT /* status */)
  2742. {
  2743.     return HXR_OK;
  2744. }
  2745. HX_RESULT
  2746. HXFileSource::CFileReader::GetFile(IHXFileObject* /*IN*/ pFile)
  2747. {
  2748.     HX_RESULT   ret = HXR_OK;
  2749.     if (m_bGetFilePending || !m_pOwner)
  2750.     {
  2751.         return HXR_FAILED;
  2752.     }
  2753.     Close();
  2754.     // get our own IHXFileResponse interface
  2755.     IHXFileResponse* pFileResponse = NULL;
  2756.     ret = QueryInterface(IID_IHXFileResponse, (void**) &pFileResponse);
  2757.     if (pFile != NULL)
  2758.     {
  2759. m_pFile = pFile;
  2760. m_pFile->AddRef();
  2761.     
  2762. if (pFileResponse)
  2763. {
  2764.     ret = m_pFile->Init(HX_FILE_READ | HX_FILE_BINARY,
  2765. pFileResponse);
  2766. }
  2767.     }
  2768.     if (FAILED(ret))
  2769.     {
  2770.         m_pOwner->GetFileDone(HXR_FAIL, NULL);
  2771.     }
  2772.     else
  2773.     {
  2774.         m_bGetFilePending = TRUE;
  2775.     }
  2776.     
  2777.     HX_RELEASE(pFileResponse);
  2778.     return ret;
  2779. }
  2780. void
  2781. HXFileSource::CFileReader::Close(void)
  2782. {
  2783.     m_bGetFilePending = FALSE;
  2784.     HX_RELEASE(m_pBuffer);
  2785.     HX_RELEASE(m_pFile);
  2786. }