📄 hxflsrc.cpp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#include "hxcom.h"
#include "hlxclib/stdio.h"
#include "hxassert.h"
#include "hxslist.h"
#include "hxcomm.h"
#include "hxengin.h"
#include "ihxpckts.h"
#include "hxplugn.h"
#include "hxfiles.h"
#include "hxformt.h"
#include "hxmeta.h"
#include "hxcore.h"
#include "hxprefs.h"
#include "hxausvc.h"
#include "hxgroup.h"
#include "hxsmbw.h"
#include "hxstring.h"
#include "chxeven.h"
#include "chxelst.h"
#include "strminfo.h"
#include "hxflsrc.h"
//#include "raevents.h"
#include "hxtick.h"
#include "hxplay.h"
#include "hxtypes.h"
#include "timeval.h"
#include "pq.h"
#include "hxsched.h"
#include "hxstat.h"
#include "dbcs.h"
#include "hxcleng.h"
#include "hxauth.h"
#include "hxrquest.h"
#include "hxstrutl.h"
#include "hxupgrd.h"
#include "srcinfo.h"
#include "plghand2.h"
#include "rmfftype.h"
#include "hxxfile.h"
#include "upgrdcol.h"
#include "uri_schemes.h"
#include "stream_desc_hlpr.h"
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
#define FILEREAD_SIZE 4096
HXFileSource::HXFileSource()
: m_lRefCount(0)
, m_pFSObject(NULL)
, m_pFFObject(NULL)
, m_pRAMFFObject(NULL)
, m_pFileResponse(NULL)
, m_pFileFormatEnumerator(NULL)
, m_pCurrentFileFormatUnk(NULL)
, m_bCurrentFileFormatUnkInUse(FALSE)
, m_pFileObject(NULL)
, m_pRequestHandler(NULL)
, m_pMimeType(NULL)
, m_pExtension(NULL)
, m_pMimeFinderResponse(NULL)
, m_ulLastBufferingReturned(0)
, m_ulMaxPreRoll(0)
, m_uNumStreamsToBeFilled(0)
, m_bInFillMode(FALSE)
, m_llFillEndTime(0)
, m_llLastFillEndTime (0)
, m_bInitialPacket(TRUE)
, m_bFastStartInProgress(FALSE)
, m_bAddDefaultUpgrade(FALSE)
, m_pDefaultUpgradeString(NULL)
#if defined(HELIX_FEATURE_ASM)
, m_pSimulatedSourceBandwidth(NULL)
#endif /* HELIX_FEATURE_ASM */
, m_bValidateMetaDone(FALSE)
, m_pFileRecognizer(NULL)
, m_pFileReader(NULL)
{
m_bAltURL = FALSE;
m_bPerfectPlay = TRUE;
}
HXFileSource::~HXFileSource()
{
DoCleanup();
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::QueryInterface
// Purpose:
// Implement this to export the interfaces supported by your
// object.
//
STDMETHODIMP
HXFileSource::QueryInterface(REFIID riid, void** ppvObj)
{
if (HXSource::QueryInterface(riid, ppvObj) == HXR_OK)
{
return HXR_OK;
}
else if (IsEqualIID(riid, IID_IHXRegistryID))
{
AddRef();
*ppvObj = (IHXRegistryID*)this;
return HXR_OK;
}
else if (IsEqualIID(riid, IID_IHXFormatResponse))
{
AddRef();
*ppvObj = (IHXFormatResponse*)this;
return HXR_OK;
}
// XXX HP
// we assume the FF object doesn't QI from its m_pContext within
// its ::QueryInterface(), otherwise we are in trouble!! - indefinite
// loop
// This is for IHXBackChannel, IHXASMSource
else if (m_pFFObject && m_pFFObject->QueryInterface(riid, ppvObj) == HXR_OK)
{
return HXR_OK;
}
#if defined(HELIX_FEATURE_ASM)
else if (m_pSimulatedSourceBandwidth &&
m_pSimulatedSourceBandwidth->QueryInterface(riid, ppvObj) == HXR_OK)
{
return HXR_OK;
}
#endif /* HELIX_FEATURE_ASM */
else if (m_pPlayer &&
m_pPlayer->QueryInterface(riid, ppvObj) == HXR_OK)
{
return HXR_OK;
}
// we don't have m_pPlayer during AutoConfig
else if (m_pEngine &&
m_pEngine->QueryInterface(riid, ppvObj) == HXR_OK)
{
return HXR_OK;
}
*ppvObj = NULL;
return HXR_NOINTERFACE;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::AddRef
// Purpose:
// Everyone usually implements this the same... feel free to use
// this implementation.
//
STDMETHODIMP_(ULONG32)
HXFileSource::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::Release
// Purpose:
// Everyone usually implements this the same... feel free to use
// this implementation.
//
STDMETHODIMP_(ULONG32)
HXFileSource::Release()
{
if (InterlockedDecrement(&m_lRefCount) > 0)
{
return m_lRefCount;
}
delete this;
return 0;
}
void
HXFileSource::ReSetup()
{
m_ulLastBufferingReturned = 0;;
m_ulFirstPacketTime = 0;
m_llFillEndTime = 0;
m_llLastFillEndTime = 0;
m_ulMaxPreRoll = 0;
m_uNumStreamsToBeFilled = 0;
m_bInitialized = FALSE;
m_bInFillMode = FALSE;
m_bInitialPacket = TRUE;
m_bFastStartInProgress = FALSE;
m_ulStreamHeadersExpected = 0;
if (m_pURL)
{
CHXURL* pURL = new CHXURL(*m_pURL);
#if defined(HELIX_FEATURE_SMIL_REPEAT)
if (m_pSourceInfo)
{
CHXSimpleList* pRepeatList = m_pSourceInfo->m_bLeadingSource?m_pSourceInfo->m_pRepeatList:
m_pSourceInfo->m_pPeerSourceInfo->m_pRepeatList;
if (pRepeatList)
{
RepeatInfo* pRepeatInfo = (RepeatInfo*)pRepeatList->GetAt(m_pSourceInfo->m_curPosition);
m_ulDelay = m_pSourceInfo->m_ulRepeatDelayTimeOffset + pRepeatInfo->ulDelay;
if (m_pSourceInfo->m_bRepeatIndefinite &&
m_pSourceInfo->m_ulMaxDuration &&
m_ulDelay + pRepeatInfo->ulDuration > m_ulOriginalDelay + m_pSourceInfo->m_ulMaxDuration)
{
m_ulRestrictedDuration = m_ulOriginalDelay + m_pSourceInfo->m_ulMaxDuration - m_ulDelay;
}
else
{
m_ulRestrictedDuration = pRepeatInfo->ulDuration;
}
}
}
#endif /* HELIX_FEATURE_SMIL_REPEAT */
#if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
m_pStats->Reset();
#endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
m_bReSetup = TRUE;
Setup(pURL, FALSE);
delete pURL;
}
return;
}
// pURL may be in the form of URL
// events will be opened as a separate source by HXPlayer...
HX_RESULT
HXFileSource::Setup(const CHXURL* pURL, BOOL bAltURL)
{
HX_RESULT theErr = HXR_OK;
IUnknown* pUnknown = NULL;
IUnknown* pObject = NULL;
IHXPlugin* pHXPlugin = NULL;
mLastError = HXR_OK;
if (!pURL)
{
return( HXR_INVALID_PATH );
}
const char* purl = pURL->GetURL();
if (!purl || !*purl)
{
return( HXR_INVALID_PATH );
}
if (!m_bReSetup)
{
theErr = SetupRegistry();
m_ulOriginalDelay = m_ulDelay;
}
ReadPreferences();
HX_VECTOR_DELETE(m_pszURL);
HX_DELETE(m_pURL);
if (!theErr && pURL)
{
m_pszURL = new char[strlen(purl) + 1];
if (m_pszURL)
{
strcpy(m_pszURL, purl); /* Flawfinder: ignore */
m_pURL = new CHXURL(*pURL);
if( !m_pURL )
{
theErr = HXR_OUTOFMEMORY;
}
}
else
{
theErr = HXR_OUTOFMEMORY;
}
}
#if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
if (!theErr && m_pStats)
{
// save URL to the registry
if (m_pStats->m_pSourceName && m_pszURL)
{
m_pStats->m_pSourceName->SetStr((char*)m_pszURL);
}
// update transport mode(local machine)
if (m_pStats->m_pTransportMode && m_pURL)
{
UINT16 uProtocol = m_pURL->GetProtocol();
if (uProtocol == httpProtocol)
{
m_pStats->m_pTransportMode->SetStr("HTTP");
}
else
{
m_pStats->m_pTransportMode->SetStr("Local");
}
}
}
#endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY*/
#if defined(HELIX_FEATURE_ASM) && defined(HELIX_FEATURE_REGISTRY)
if (!theErr && m_pPlayer && !m_pSimulatedSourceBandwidth && m_pRegistry)
{
/* Check if the core is used for simulated network playback for
* local files. This feature is used by the Tools group
* for Preview mode at different bandwidths.
*/
INT32 lUseNetBandwidth = 0;
if ((m_pRegistry->GetIntByName("UseNetBandwidthForLocalPlayback",
lUseNetBandwidth) == HXR_OK) &&
(lUseNetBandwidth == 1))
{
m_pSimulatedSourceBandwidth = new SourceBandwidthInfo;
m_pSimulatedSourceBandwidth->AddRef();
}
}
#endif /* HELIX_FEATURE_ASM && HELIX_FEATURE_REGISTRY*/
if (!theErr)
{
const char* pProtocolEnd = HXFindChar(purl,':');
if (!pProtocolEnd)
{
goto exit;
}
int nLength = pProtocolEnd - purl;
CHXString strProtocol(purl,nLength);
IHXPlugin2Handler* pPlugin2Handler;
if (HXR_OK != m_pEngine->QueryInterface(IID_IHXPlugin2Handler, (void**)&pPlugin2Handler))
{
theErr = HXR_UNEXPECTED;
goto exit;
}
if (HXR_OK == pPlugin2Handler->FindPluginUsingStrings(PLUGIN_CLASS, PLUGIN_FILESYSTEM_TYPE,
PLUGIN_FILESYSTEMPROTOCOL, (char*)(const char*)strProtocol, NULL, NULL, pUnknown))
{
pUnknown->QueryInterface(IID_IHXFileSystemObject, (void**) &m_pFSObject);
HX_RELEASE(pUnknown);
}
else
{
MergeUpgradeRequest(TRUE, (char*)(const char*) strProtocol);
theErr = HXR_NO_FILESYSTEM;
}
HX_RELEASE(pPlugin2Handler);
// Initialize the File System plugin...
if (!theErr)
{
if (HXR_OK != m_pFSObject->QueryInterface(IID_IHXPlugin,(void**)&pHXPlugin))
{
theErr = HXR_NOT_INITIALIZED;
goto exit;
}
if (HXR_OK != pHXPlugin->InitPlugin((IUnknown*) (IHXStreamSource*)this))
{
theErr = HXR_NOT_INITIALIZED;
goto exit;
}
}
// Create a FileObject in order to determine the mime-type of the file
if (!theErr)
{
// Create the file object...
if (HXR_OK != m_pFSObject->CreateFile(&pObject))
{
theErr = HXR_NOT_INITIALIZED;
goto exit;
}
if ((HXR_OK != pObject->QueryInterface(IID_IHXFileObject,
(void**)&m_pFileObject)) ||
(HXR_OK != pObject->QueryInterface(IID_IHXRequestHandler,
(void**)&m_pRequestHandler)))
{
theErr = HXR_NOT_INITIALIZED;
goto exit;
}
IHXHTTPRedirect* pHttpRedirect = NULL;
m_pFileObject->QueryInterface(IID_IHXHTTPRedirect, (void**)&pHttpRedirect);
if (pHttpRedirect)
{
pHttpRedirect->SetResponseObject((IHXHTTPRedirectResponse*) this);
pHttpRedirect->Release();
}
// set request
SetRequest(m_pURL, bAltURL);
// we want to protect against the TLC opening another URL
m_pPlayer->SetModal(TRUE);
theErr = m_pRequestHandler->SetRequest(m_pRequest);
m_pPlayer->SetModal(FALSE);
if (theErr != HXR_OK)
{
theErr = HXR_NOT_INITIALIZED;
goto exit;
}
theErr = ExtendedSetup(purl);
}
}
exit:
HX_RELEASE(pHXPlugin);
HX_RELEASE(pObject);
if (theErr)
{
HX_RELEASE(m_pFSObject);
}
return theErr;
}
HX_RESULT
HXFileSource::ExtendedSetup(const char* pszURL)
{
HX_RESULT theErr = HXR_OK;
char* pszTemp = NULL;
const char* pMimeType = NULL;
IHXBuffer* pValue = NULL;
IHXValues* pResponseHeaders = NULL;
IHXFileMimeMapper* pFileMimeMapper = NULL;
/* Does the file object support finding of mime types */
if (HXR_OK == m_pFileObject->QueryInterface(IID_IHXFileMimeMapper,(void**)&pFileMimeMapper))
{
if (!m_pMimeFinderResponse)
{
// Initialize our MimeFinder!
m_pMimeFinderResponse = new CMimeFinderFileResponse(this);
if (!m_pMimeFinderResponse)
{
theErr = HXR_NOT_INITIALIZED;
}
else
{
m_pMimeFinderResponse->AddRef();
}
}
// Init the file object, and ask for the mime type!
if (!theErr && HXR_OK != pFileMimeMapper->FindMimeType(pszURL, m_pMimeFinderResponse))
{
theErr = HXR_DOC_MISSING;
}
HX_RELEASE(pFileMimeMapper);
}
else
{
if (HXR_OK == m_pRequest->GetResponseHeaders(pResponseHeaders) &&
pResponseHeaders)
{
if (HXR_OK == pResponseHeaders->GetPropertyCString("Content-Type", pValue) &&
pValue)
{
pMimeType = (char*)pValue->GetBuffer();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -