hxsrc.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:68k
- /* ***** 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 "hxtypes.h"
- #include "hxcom.h"
- #ifdef _WINDOWS
- #include <windows.h>
- #endif
- #include "hlxclib/stdio.h"
- #include "hlxclib/stdlib.h"
- #include "prefdefs.h"
- #include "plprefk.h"
- #include "hxcomm.h"
- #include "ihxpckts.h"
- #include "hxfiles.h"
- #include "hxengin.h"
- #include "hxcore.h"
- #include "hxprefs.h"
- #include "hxpref.h"
- #include "hxausvc.h"
- #include "hxmon.h"
- #include "hxclreg.h"
- #include "hxgroup.h"
- #include "hxsmbw.h"
- #include "hxstrm.h"
- #include "hxwin.h"
- #include "hxcore.h"
- #include "hxhyper.h"
- #include "playhpnv.h"
- #include "hxplugn.h"
- #include "hxrendr.h"
- #include "chxeven.h"
- #include "chxelst.h"
- #include "hxmap.h"
- #include "hxrquest.h"
- #include "hxmangle.h"
- #include "hxtick.h"
- #include "dbcs.h"
- #include "hxstrutl.h"
- #include "strminfo.h"
- #include "timeval.h"
- #include "statsmgr.h"
- #include "hxbsrc.h"
- #include "hxsrc.h"
- #include "srcinfo.h"
- #include "corshare.h"
- #include "upgrdcol.h"
- #include "hxrasyn.h"
- #include "hxaudstr.h"
- #include "hxplugn.h"
- #include "hxrendr.h"
- #include "errdbg.h"
- // will be taken out once flags are defined in a separate file
- #include "rmfftype.h"
- #include "hxplay.h"
- #include "hxcleng.h"
- #include "hxsrc.h"
- #include "hxheap.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #endif
- #if defined(HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
- // TurboPlay should never be turned on in low heap mode, but just in case ...
- #define TURBO_AUDIO_PUSHDOWN 100
- #else
- #define TURBO_AUDIO_PUSHDOWN 2000
- #endif
- HXSource::HXSource() :
- m_pPlayer (0)
- , m_lRefCount(0)
- , m_ulStreamIndex(0)
- , m_bInitialized (FALSE)
- , m_bIsPreBufferingDone(FALSE)
- , m_bClipTimeAdjusted(FALSE)
- , mLastError (HXR_OK)
- , m_ulPerfectPlayTime (0)
- , m_ulBufferedPlayTime(0)
- , m_ulStreamHeadersExpected(0)
- , m_bPerfectPlayEntireClip(FALSE)
- , m_bCannotBufferEntireClip(FALSE)
- , m_uNumStreams (0)
- , mFlags (0)
- , m_bPerfectPlayAllowed (FALSE)
- , mSaveAsAllowed (FALSE)
- , mLiveStream (FALSE)
- , m_bRestrictedLiveStream (FALSE)
- , m_bSourceEnd (FALSE)
- , m_bForcedSourceEnd(FALSE)
- , m_ulPreRollInMs (0)
- , m_ulPreRoll (0)
- , m_ulAvgBandwidth (0)
- , m_ulDuration (0)
- , m_bReceivedData (FALSE)
- , m_bReceivedHeader(FALSE)
- , m_bNonSeekable(FALSE)
- , m_nSeeking (0)
- , m_bPaused (FALSE)
- , m_bFirstResume(TRUE)
- , m_bResumePending(FALSE)
- , m_bIsActive(FALSE)
- , m_uActiveStreams (0)
- , m_pszURL(NULL)
- , m_pURL(NULL)
- , m_bAltURL(TRUE)
- , m_ulStartTime (0)
- , m_ulEndTime (0)
- , m_ulDelay (0)
- , m_ulOriginalDelay (0)
- , m_ulPrefetchDelay (0)
- , m_llLastExpectedPacketTime(0)
- , m_ulRestrictedDuration(0)
- , m_bDelayed(FALSE)
- , m_ulSourceStartTime(0)
- , m_pPreferences (0)
- , m_pRegistry (0)
- , m_pScheduler (0)
- #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
- , m_pStats (0)
- , m_pStatsManager(NULL)
- #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
- , m_bLocked (FALSE)
- , m_pEngine (0)
- , m_bRebufferingRequired(FALSE)
- , m_bInitialBuffering(TRUE)
- , m_bPartOfNextGroup(FALSE)
- , m_bPartOfPrefetchGroup(FALSE)
- , m_pBufferManager(NULL)
- , m_pFileHeader(0)
- , m_bPerfectPlay(FALSE)
- , m_bBufferedPlay(FALSE)
- , m_ulLossHack(0)
- , m_ulNumFakeLostPackets(0)
- , m_ulLastBufferingCalcTime(0)
- , m_pSourceInfo(NULL)
- , m_pRequest(NULL)
- , m_pASMSource(NULL)
- , m_pBackChannel(NULL)
- , m_bDefaultAltURL(FALSE)
- , m_bCustomEndTime(FALSE)
- , m_bCustomDuration(FALSE)
- , m_bIsPreBufferingStarted(FALSE)
- , m_ulOriginalDuration(0)
- , m_bReSetup(FALSE)
- #if defined(HELIX_FEATURE_AUTOUPGRADE)
- , m_pUpgradeCollection(NULL)
- #endif /* HELIX_FEATURE_AUTOUPGRADE */
- , m_bRTSPRuleFlagWorkAround(FALSE)
- , m_bContinueWithHeaders(FALSE)
- , m_bPrefetch(FALSE)
- , m_prefetchType(PrefetchUnknown)
- , m_ulPrefetchValue(0)
- , m_ulFirstPacketTime(0)
- , m_bIsMeta(FALSE)
- , m_bFastStart(FALSE)
- , m_serverTurboPlay(TURBO_PLAY_UNKNOWN)
- , m_ulMaxBandwidth(4000) // 4000kbps
- , m_pAudioStreamList(NULL)
- , m_maxPossibleAccelRatio(4.0) // I donno what's a good value?
- , m_ulTurboPushDown(TURBO_AUDIO_PUSHDOWN)
- , m_bSureStreamClip(FALSE)
- , m_ulTurboStartActiveTime(0)
- , m_srcEndCode(END_UNKNOWN)
- , m_pRecordControl(NULL)
- , m_bPlayFromRecordControl(FALSE)
- , m_pRedirectURL(NULL)
- , m_bRedirectPending(FALSE)
- {
- mStreamInfoTable = new CHXMapLongToObj;
- }
- HXSource::~HXSource()
- {
- // XXX moved this to the distuctor because we want to keep arround
- // the request until the renderers are close at which point we should
- // be released and deleted.
- HX_RELEASE(m_pRequest);
- HX_VECTOR_DELETE(m_pszURL);
- HX_DELETE(mStreamInfoTable);
- }
- void
- HXSource::Stop()
- {
- m_pSourceInfo = NULL;
- HX_DELETE (m_pURL);
- HX_DELETE (m_pBufferManager);
- if ( FAILED(mLastError) )
- {
- HX_RELEASE(m_pRequest);
- }
- #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
- if (m_pStatsManager)
- {
- m_pStatsManager->DoCleanup();
- HX_RELEASE(m_pStatsManager);
- }
- HX_DELETE(m_pStats);
- #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
- DeleteAllEvents();
- HX_RELEASE(m_pRegistry);
- HX_RELEASE(m_pPreferences);
- HX_RELEASE(m_pScheduler);
- HX_RELEASE(m_pEngine);
- }
- HX_RESULT HXSource::DoCleanup(EndCode endCode)
- {
- m_ulDuration = 0;
- m_ulPreRollInMs = 0;
- m_ulPreRoll = 0;
- m_ulAvgBandwidth = 0;
- m_ulLastBufferingCalcTime = 0;
- m_ulMaxBandwidth = 0;
- m_serverTurboPlay = TURBO_PLAY_UNKNOWN;
- m_bAltURL = FALSE;
- m_bPaused = FALSE;
- m_bFirstResume = TRUE;
- m_bIsActive = FALSE;
- m_bResumePending = FALSE;
- m_bIsPreBufferingStarted = FALSE;
- m_bIsPreBufferingDone = FALSE;
- m_bClipTimeAdjusted = FALSE;
- m_bInitialBuffering = TRUE;
- m_bRebufferingRequired = FALSE;
- m_bReceivedData = FALSE;
- m_bReceivedHeader = FALSE;
- ReleaseAudioStreams(m_pAudioStreamList);
- HX_DELETE(m_pAudioStreamList);
- DeleteStreamTable();
- CHXSimpleList::Iterator lIter = m_HXStreamList.Begin();
- for (; lIter != m_HXStreamList.End(); ++lIter)
- {
- HXStream* pStream = (HXStream*) (*lIter);
- pStream->Release();
- }
- m_HXStreamList.RemoveAll();
- HX_RELEASE(m_pFileHeader);
- HX_RELEASE(m_pASMSource);
- HX_RELEASE(m_pBackChannel);
- #if defined(HELIX_FEATURE_AUTOUPGRADE)
- HX_RELEASE(m_pUpgradeCollection);
- #endif /* HELIX_FEATURE_AUTOUPGRADE */
- m_bForcedSourceEnd = FALSE;
- m_bSourceEnd = FALSE;
- HX_DELETE(m_pRedirectURL);
- m_bRedirectPending = FALSE;
- #if defined(HELIX_FEATURE_RECORDCONTROL)
- if(m_pRecordControl)
- {
- m_pRecordControl->Cleanup();
- }
- #endif /* HELIX_FEATURE_RECORDCONTROL */
- HX_RELEASE(m_pRecordControl);
- return HXR_OK;
- }
- /////////////////////////////////////////////////////////////////////////
- // Method:
- // IUnknown::QueryInterface
- // Purpose:
- // Implement this to export the interfaces supported by your
- // object.
- //
- STDMETHODIMP HXSource::QueryInterface(REFIID riid, void** ppvObj)
- {
- QInterfaceList qiList[] =
- {
- { GET_IIDHANDLE(IID_IHXStreamSource), (IHXStreamSource*)this },
- { GET_IIDHANDLE(IID_IHXPendingStatus), (IHXPendingStatus*)this },
- { GET_IIDHANDLE(IID_IHXInfoLogger), (IHXInfoLogger*)this },
- { GET_IIDHANDLE(IID_IHXPrivateStreamSource), (IHXPrivateStreamSource*)this },
- { GET_IIDHANDLE(IID_IHXSourceBufferingStats), (IHXSourceBufferingStats*)this },
- { GET_IIDHANDLE(IID_IHXSourceBufferingStats2), (IHXSourceBufferingStats2*)this },
- #if defined(HELIX_FEATURE_HYPER_NAVIGATE)
- { GET_IIDHANDLE(IID_IHXHyperNavigate), (IHXHyperNavigate*)this },
- { GET_IIDHANDLE(IID_IHXHyperNavigate2), (IHXHyperNavigate2*)this },
- #endif /* defined(HELIX_FEATURE_HYPER_NAVIGATE) */
- { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXStreamSource*)this },
- };
-
- HX_RESULT res = ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
-
- // if successful, return immediately...
- if (SUCCEEDED(res))
- {
- return res;
- }
- // ... otherwise proceed onward
-
- if (IsEqualIID(riid, IID_IHXBackChannel))
- {
- if (m_pBackChannel)
- {
- AddRef();
- *ppvObj = (IHXBackChannel*)this;
- return HXR_OK;
- }
- else
- {
- *ppvObj = NULL;
- return HXR_NOINTERFACE;
- }
- }
- else if (IsEqualIID(riid, IID_IHXASMSource))
- {
- if (m_pASMSource)
- {
- AddRef();
- *ppvObj = (IHXASMSource*)this;
- return HXR_OK;
- }
- else
- {
- *ppvObj = NULL;
- return HXR_NOINTERFACE;
- }
- }
- #if defined(HELIX_FEATURE_AUTOUPGRADE)
- else if (IsEqualIID(riid, IID_IHXUpgradeCollection))
- {
- if (!m_pUpgradeCollection)
- {
- m_pUpgradeCollection = new HXUpgradeCollection;
- m_pUpgradeCollection->AddRef();
- }
- return m_pUpgradeCollection->QueryInterface(riid, ppvObj);
- }
- #endif /* HELIX_FEATURE_AUTOUPGRADE */
- else if (m_pRequest &&
- m_pRequest->QueryInterface(riid, ppvObj) == HXR_OK)
- {
- return HXR_OK;
- }
- else if (m_pFileHeader &&
- m_pFileHeader->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) HXSource::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- /////////////////////////////////////////////////////////////////////////
- // Method:
- // IUnknown::Release
- // Purpose:
- // Everyone usually implements this the same... feel free to use
- // this implementation.
- //
- STDMETHODIMP_(ULONG32) HXSource::Release()
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- // *** IHXStreamSource methods ***
- /************************************************************************
- * Method:
- * IHXStreamSource::IsLive
- * Purpose:
- * Ask the source whether it is live
- *
- */
- STDMETHODIMP_ (BOOL) HXSource::IsLive(void)
- {
- return mLiveStream;
- }
- /************************************************************************
- * Method:
- * IHXStreamSource::GetPlayer
- * Purpose:
- * Get the interface to the player object of which the source is
- * a part of.
- *
- */
- STDMETHODIMP HXSource::GetPlayer(IHXPlayer* &pPlayer)
- {
- pPlayer = m_pPlayer;
- if (pPlayer)
- {
- pPlayer->AddRef();
- }
- return HXR_OK;
- }
- /************************************************************************
- * Method:
- * IHXStreamSource::GetContext
- * Purpose:
- * Get the interface to the context object of which the source is
- * a part of.
- *
- */
- STDMETHODIMP HXSource::GetContext(IUnknown* &pContext)
- {
- pContext = ((IUnknown*)(IHXClientEngine*) m_pEngine);
- if (pContext)
- {
- pContext->AddRef();
- }
- return HXR_OK;
- }
- /************************************************************************
- * Method:
- * IHXStreamSource::GetURL
- * Purpose:
- * Get the URL for this source. NOTE: The returned string is
- * assumed to be valid for the life of the IHXStreamSource from which it
- * was returned.
- *
- */
- STDMETHODIMP_(const char*) HXSource::GetURL(void)
- {
- const char* pURL = NULL;
- /*
- * Make sure that the we have not been re-directed
- * to a new URL.
- */
- if (m_pRequest &&
- m_pRequest->GetURL(pURL) == HXR_OK &&
- pURL)
- {
- if (!m_pszURL ||
- ::strcasecmp(pURL, m_pszURL) != 0)
- {
- HX_VECTOR_DELETE(m_pszURL);
- m_pszURL = new char[strlen(pURL) + 1];
- strcpy(m_pszURL, pURL); /* Flawfinder: ignore */
- }
- }
- // append RAM mimeType as URL option to notify the
- // caller(i.e. ViewSource)
- if (m_bIsMeta)
- {
- char* pszTemp = NULL;
- pszTemp = ::HXFindChar(m_pszURL, '?');
- if (pszTemp)
- {
- int lenTemp = strlen(m_pszURL) + strlen("&mimeType=") + strlen(RAM_MIMETYPE) + 1;
- pszTemp = new char[lenTemp];
- SafeSprintf(pszTemp, lenTemp, "%s%s%s", m_pszURL, "&mimeType=", RAM_MIMETYPE); /* Flawfinder: ignore */
- }
- else
- {
- int lenTemp = strlen(m_pszURL) + strlen("?mimeType=") + strlen(RAM_MIMETYPE) + 1;
- pszTemp = new char[lenTemp];
- SafeSprintf(pszTemp, lenTemp, "%s%s%s", m_pszURL, "?mimeType=", RAM_MIMETYPE); /* Flawfinder: ignore */
- }
- HX_VECTOR_DELETE(m_pszURL);
- m_pszURL = pszTemp;
- }
- return m_pszURL;
- }
- /************************************************************************
- * Method:
- * IHXStreamSource::GetStreamCount
- * Purpose:
- * Get the number of streams in this source
- *
- */
- STDMETHODIMP_(UINT16)
- HXSource::GetStreamCount()
- {
- return m_HXStreamList.GetCount();
- }
- /************************************************************************
- * Method:
- * IHXStreamSource::GetStream
- * Purpose:
- * Get the stream with the given index.
- * Note:
- * Since stream numbers may not be zero based, stream index is not
- * equal to the stream number. Actual stream number may be determined
- * from IHXStream::GetStreamNumber()
- *
- */
- STDMETHODIMP
- HXSource::GetStream
- (
- UINT16 nIndex,
- REF(IUnknown*) pUnknown
- )
- {
- LISTPOSITION lPosition = m_HXStreamList.FindIndex((int) nIndex);
- if (!lPosition)
- {
- pUnknown = NULL;
- return HXR_INVALID_PARAMETER;
- }
- HXStream* pStream = (HXStream*) m_HXStreamList.GetAt(lPosition);
- HX_ASSERT(pStream);
- return pStream->QueryInterface(IID_IUnknown,(void**)&pUnknown);
- }
- // IHXPrivateStreamSource methods
- STDMETHODIMP_(BOOL) HXSource::IsSaveAllowed()
- {
- return mSaveAsAllowed;
- }
- /*
- * IHXBackChannel method
- */
- /************************************************************************
- * Method:
- * IHXBackChannel::PacketReady
- * Purpose:
- * A back channel packet sent from Renderer to FileFormat plugin.
- */
- STDMETHODIMP
- HXSource::PacketReady(IHXPacket* pPacket)
- {
- HX_ASSERT(m_pBackChannel);
- if (m_pBackChannel)
- {
- return m_pBackChannel->PacketReady(pPacket);
- }
- return HXR_FAIL;
- }
- /*
- * IHXASMSource methods
- */
- /************************************************************************
- * Method:
- * IHXASMSource::Subscribe
- * Purpose:
- * Called to inform a file format that a subscription has occurred,
- * to rule number uRuleNumber, for stream uStreamNumber.
- */
- STDMETHODIMP
- HXSource::Subscribe(UINT16 uStreamNumber,
- UINT16 uRuleNumber)
- {
- HX_ASSERT(m_pASMSource);
- if (m_pASMSource)
- {
- return m_pASMSource->Subscribe(uStreamNumber, uRuleNumber);
- }
- return HXR_FAIL;
- }
- /************************************************************************
- * Method:
- * IHXASMSource::Unsubscribe
- * Purpose:
- * Called to inform a file format that a unsubscription has occurred,
- * to rule number uRuleNumber, for stream uStreamNumber.
- */
- STDMETHODIMP
- HXSource::Unsubscribe(UINT16 uStreamNumber,
- UINT16 uRuleNumber)
- {
- HX_ASSERT(m_pASMSource);
- if (m_pASMSource)
- {
- return m_pASMSource->Unsubscribe(uStreamNumber, uRuleNumber);
- }
- return HXR_FAIL;
- }
- void
- HXSource::AddHXStream(HXStream* pStream)
- {
- pStream->AddRef();
- m_HXStreamList.AddTail(pStream);
- UINT16 uStreamNumber = pStream->GetStreamNumber();
- STREAM_INFO* pStreamInfo;
- if (mStreamInfoTable->Lookup((LONG32) uStreamNumber, (void*& )pStreamInfo))
- {
- pStreamInfo->m_pStream = pStream;
- pStreamInfo->m_pStream->AddRef();
- pStreamInfo->BufferingState().OnStream((IHXStream*)pStream);
- }
- }
- HX_RESULT
- HXSource::CollectAudioStreams(CHXSimpleList*& pAudioStreamList)
- {
- #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
- HX_RESULT rc = HXR_OK;
- UINT16 i = 0;
- UINT16 uNumAudioStreams = 0;
- CHXAudioPlayer* pAudioPlayer = NULL;
- CHXAudioStream* pCHXAudioStream = NULL;
- IHXValues* pHeader = NULL;
- pAudioStreamList = NULL;
- if (!m_pPlayer)
- {
- goto cleanup;
- }
- pAudioPlayer = m_pPlayer->GetAudioPlayer();
- if (!pAudioPlayer)
- {
- goto cleanup;
- }
- uNumAudioStreams = pAudioPlayer->GetAudioStreamCount();
- for (i = 0; i < uNumAudioStreams; i++)
- {
- pCHXAudioStream = pAudioPlayer->GetCHXAudioStream(i);
- pCHXAudioStream->AddRef();
- pHeader = ((IHXAudioStream*)pCHXAudioStream)->GetStreamInfo();
- if (pHeader &&
- IsAudioStreamFromThisSource(pHeader))
- {
- if (!pAudioStreamList)
- {
- pAudioStreamList = new CHXSimpleList();
- }
- pAudioStreamList->AddTail(pCHXAudioStream);
- }
- else
- {
- HX_RELEASE(pCHXAudioStream);
- }
- HX_RELEASE(pHeader);
- }
- cleanup:
- if (!pAudioStreamList)
- {
- rc = HXR_FAILED;
- }
- return rc;
- #else
- return HXR_NOTIMPL;
- #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
- }
- void
- HXSource::RemoveAudioStreams(void)
- {
- #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
- CHXAudioPlayer* pAudioPlayer = NULL;
- CHXSimpleList* pAudioStreamList = NULL;
- if (!m_pPlayer)
- {
- goto cleanup;
- }
- pAudioPlayer = m_pPlayer->GetAudioPlayer();
- if (!pAudioPlayer)
- {
- goto cleanup;
- }
- pAudioPlayer->AddRef();
- if (HXR_OK == CollectAudioStreams(pAudioStreamList) && pAudioStreamList)
- {
- pAudioPlayer->ManageAudioStreams(pAudioStreamList, CHXAudioPlayer::STR_REMOVE);
- ReleaseAudioStreams(pAudioStreamList);
- HX_DELETE(pAudioStreamList);
- }
- HX_RELEASE(pAudioPlayer);
- cleanup:
- #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
- return;
- }
- void
- HXSource::PauseAudioStreams(void)
- {
- #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
- CHXAudioPlayer* pAudioPlayer = NULL;
- CHXSimpleList* pAudioStreamList = NULL;
- if (!m_pPlayer)
- {
- goto cleanup;
- }
- pAudioPlayer = m_pPlayer->GetAudioPlayer();
- if (!pAudioPlayer)
- {
- goto cleanup;
- }
- pAudioPlayer->AddRef();
- if (HXR_OK == CollectAudioStreams(pAudioStreamList) && pAudioStreamList)
- {
- pAudioPlayer->ManageAudioStreams(pAudioStreamList, CHXAudioPlayer::STR_PAUSE);
- ReleaseAudioStreams(pAudioStreamList);
- HX_DELETE(pAudioStreamList);
- }
- HX_RELEASE(pAudioPlayer);
- cleanup:
- #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
- return;
- }
- void
- HXSource::ResumeAudioStreams(void)
- {
- #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
- CHXAudioPlayer* pAudioPlayer = NULL;
- CHXSimpleList* pAudioStreamList = NULL;
- if (!m_pPlayer)
- {
- goto cleanup;
- }
- pAudioPlayer = m_pPlayer->GetAudioPlayer();
- if (!pAudioPlayer)
- {
- goto cleanup;
- }
- pAudioPlayer->AddRef();
- if (HXR_OK == CollectAudioStreams(pAudioStreamList) && pAudioStreamList)
- {
- pAudioPlayer->ManageAudioStreams(pAudioStreamList, CHXAudioPlayer::STR_RESUME);
- ReleaseAudioStreams(pAudioStreamList);
- HX_DELETE(pAudioStreamList);
- }
- HX_RELEASE(pAudioPlayer);
- cleanup:
- #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
- return;
- }
- void
- HXSource::ReleaseAudioStreams(CHXSimpleList* pAudioStreamList)
- {
- #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
- if (pAudioStreamList && !pAudioStreamList->IsEmpty())
- {
- CHXSimpleList::Iterator lIter = pAudioStreamList->Begin();
- for (; lIter != pAudioStreamList->End(); ++lIter)
- {
- CHXAudioStream* pAudioStream = (CHXAudioStream*) (*lIter);
- HX_RELEASE(pAudioStream);
- }
- }
- #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
- return;
- }
- HX_RESULT HXSource::Init(HXPlayer * pPlayer, UINT32 unRegistryID)
- {
- HX_RESULT theErr = HXR_OK;
-
- m_pPlayer = pPlayer;
- if (m_pPlayer->QueryInterface(IID_IHXPreferences, (void **) &m_pPreferences) != HXR_OK)
- {
- theErr = HXR_INVALID_PARAMETER; //HX_INVALID_INTERFACE;
- }
- m_pBufferManager = new CBufferManager(this);
- if(!m_pBufferManager)
- {
- theErr = HXR_OUTOFMEMORY;
- }
- // create registry entries
- if (HXR_OK != m_pPlayer->QueryInterface(IID_IHXRegistry, (void**)&m_pRegistry))
- {
- m_pRegistry = NULL;
- }
- else
- {
- m_ulRegistryID = unRegistryID;
- }
- if (!theErr &&
- m_pPlayer->QueryInterface(IID_IHXScheduler, (void **) &m_pScheduler) != HXR_OK)
- {
- theErr = HXR_INVALID_PARAMETER; //HX_INVALID_INTERFACE;
- }
- IHXPreferences* pPref = NULL;
- m_pPlayer->QueryInterface(IID_IHXPreferences, (void**)&pPref);
- if (HXR_OK == ReadPrefINT32(pPref, "TurboPushdown", m_ulTurboPushDown))
- {
- m_ulTurboPushDown = (m_ulTurboPushDown / 100) * 100; // round to multiple of 100
- }
- HX_RELEASE(pPref);
- m_pEngine = m_pPlayer->m_pEngine;
- m_pEngine->AddRef();
- return theErr;
- }
- HX_RESULT HXSource::SetupRegistry()
- {
- HX_RESULT theErr = HXR_OK;
- #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
- UINT32 ulRepeatedRegistryID = 0;
- IHXBuffer* pRepeatRegName = NULL;
- char szSourceName[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
- HX_ASSERT(m_pSourceInfo);
- if (m_pSourceInfo->m_bLeadingSource &&
- !m_pSourceInfo->m_pRepeatList)
- {
- m_pStats = new SOURCE_STATS(m_pRegistry, m_ulRegistryID);
- }
- else if (m_pRegistry &&
- HXR_OK == m_pRegistry->GetPropName(m_pPlayer->m_ulRepeatedRegistryID, pRepeatRegName))
- {
- SafeSprintf(szSourceName, MAX_DISPLAY_NAME, "%s.%ld%ld%ld",
- pRepeatRegName->GetBuffer(),
- m_pSourceInfo->m_uGroupID,
- m_pSourceInfo->m_uTrackID,
- (int)m_pSourceInfo->m_bLeadingSource);
-
- ulRepeatedRegistryID = m_pRegistry->GetId(szSourceName);
- if (!ulRepeatedRegistryID)
- {
- ulRepeatedRegistryID = m_pRegistry->AddComp(szSourceName);
- }
- m_pStatsManager = new StatsManager(m_pRegistry, m_ulRegistryID, ulRepeatedRegistryID);
- m_pStatsManager->AddRef();
- m_pStats = new SOURCE_STATS(m_pRegistry, ulRepeatedRegistryID);
- if( !m_pStats )
- {
- theErr = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- // why stats' creation failed??
- HX_ASSERT(FALSE);
- }
- HX_RELEASE(pRepeatRegName);
- #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
- return theErr;
- }
- HX_RESULT HXSource::ReadPreferences(void)
- {
- UINT32 un16Temp = 10;
- ReadPrefINT32(m_pPreferences, "PerfectPlayTime", un16Temp);
- m_ulPerfectPlayTime = un16Temp;
- ReadPrefINT32(m_pPreferences, "BufferedPlayTime", un16Temp);
- m_ulBufferedPlayTime = un16Temp;
- ReadPrefBOOL(m_pPreferences, "PerfPlayEntireClip", m_bPerfectPlayEntireClip);
- return HXR_OK;
- }
- HX_RESULT HXSource::DeleteStreamTable(void)
- {
- HX_RESULT theErr = HXR_OK;
- STREAM_INFO * sInfo = NULL;
-
- for (CHXMapLongToObj::Iterator i = mStreamInfoTable->Begin();
- i != mStreamInfoTable->End(); ++i)
- {
- sInfo = (STREAM_INFO*) (*i);
-
- if (sInfo)
- {
- HX_DELETE (sInfo);
- }
- }
- mStreamInfoTable->RemoveAll();
- m_ulStreamIndex = 0;
- m_uNumStreams = 0;
-
- return theErr;
- }
- IHXValues* HXSource::GetHeaderInfo(UINT16 stream_number)
- {
- STREAM_INFO * pStreamInfo;
- if (mStreamInfoTable->Lookup((LONG32) stream_number, (void*& )pStreamInfo))
- {
- return pStreamInfo->m_pHeader;
- }
- else
- {
- return NULL;
- }
- }
- HX_RESULT
- HXSource::GetStreamHeaderInfo(UINT16 index, IHXValues*& hdr)
- {
- HX_TRACE("HXSource::GetStreamHeaderInfo");
-
- // sanity check
- if (index >= m_uNumStreams)
- {
- return HXR_INVALID_PARAMETER; // HX_INVALID_INDEX;
- }
-
- CHXMapLongToObj::Iterator i = mStreamInfoTable->Begin();
- for (UINT16 j=0; j < index; j++)
- {
- ++i;
- }
- STREAM_INFO* pStreamInfo = (STREAM_INFO*) *i;
- hdr = pStreamInfo->m_pHeader;
- if (hdr)
- {
- hdr->AddRef();
- }
- return HXR_OK;
- }
- void HXSource::SetFlags(UINT16 flags)
- {
- mFlags = flags;
- if (mFlags & HX_PERFECT_PLAY_ENABLED)
- {
- m_bPerfectPlayAllowed = TRUE;
- }
- else
- {
- m_bPerfectPlayAllowed = FALSE;
- }
- if (mFlags & HX_SAVE_ENABLED)
- {
- mSaveAsAllowed = TRUE;
- }
- else
- {
- mSaveAsAllowed = FALSE;
- }
- }
- #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
- HX_RESULT HXSource::CopyMetaDataToRegistry(IHXValues* pHeader)
- {
- // get Request Object
- char pszServerMetaData[256] = {0}; /* Flawfinder: ignore */
- char pszMetaData[256] = {0}; /* Flawfinder: ignore */
- IHXValues* pReqHeaders = NULL;
- IHXRequest* pRequest = NULL;
- IHXBuffer* pBuffer = NULL;
- char szRegKeyName[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
- char buff[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
- char szSMDKey[256]; /* Flawfinder: ignore */
- ULONG32 ulValue = 0;
- IHXBuffer* pParentName = NULL;
- UINT32 regid = 0;
- const char szServerMetaData[] = {"ServerMetaData"};
- if (HXR_OK == m_pRegistry->GetPropName(m_pStats->m_ulRegistryID, pParentName))
- {
- SafeStrCpy(buff, (const char*) pParentName->GetBuffer(), MAX_DISPLAY_NAME);
- char* pDot = strrchr(buff, '.');
- if (pDot)
- {
- *pDot = ' ';
- }
- SafeStrCpy(szSMDKey, buff, 256);
- if (HXR_OK == GetRequest(pRequest))
- {
- // get request headers
- if (HXR_OK == pRequest->GetRequestHeaders(pReqHeaders))
- {
- // look for the meta data properties
- if (HXR_OK == pReqHeaders->GetPropertyCString("AcceptMetaInfo", pBuffer))
- {
- SafeStrCpy(pszMetaData, (char*) pBuffer->GetBuffer(), 256);
- HX_RELEASE(pBuffer);
- // look for comma delimited entries
- const char* pCharEntryStart = pszMetaData;
- const char* pCharEntryEnd = pCharEntryStart;
- while (pCharEntryEnd && *pCharEntryEnd)
- {
- ++pCharEntryEnd;
- if (*pCharEntryEnd == ',' || !*pCharEntryEnd)
- {
- // copy next prop request into buffer
- strncpy(buff, pCharEntryStart, (UINT32)pCharEntryEnd - (UINT32)pCharEntryStart); /* Flawfinder: ignore */
- *(buff+(UINT32)pCharEntryEnd - (UINT32)pCharEntryStart) = ' ';
- // see if this prop is in file header (it should be!)
- if (HXR_OK == pHeader->GetPropertyCString(buff, pBuffer))
- {
- // create new registry entry
- SafeSprintf(szRegKeyName, MAX_DISPLAY_NAME, "%s.%s", pParentName->GetBuffer(), buff);
- regid = m_pRegistry->GetId(szRegKeyName);
- if (!regid)
- {
- m_pRegistry->AddStr(szRegKeyName, pBuffer);
- }
- else
- {
- // set new value
- m_pRegistry->SetStrByName(szRegKeyName, pBuffer);
- }
- HX_RELEASE(pBuffer);
- }
- else if (HXR_OK == pHeader->GetPropertyULONG32(buff, ulValue))
- {
- // create new registry entry
- SafeSprintf(szRegKeyName, MAX_DISPLAY_NAME, "%s.%s", pParentName->GetBuffer(), buff);
- regid = m_pRegistry->GetId(szRegKeyName);
- if (!regid)
- {
- m_pRegistry->AddInt(szRegKeyName, ulValue);
- }
- else
- {
- // set new value
- m_pRegistry->SetIntByName(szRegKeyName, ulValue);
- }
- }
- pCharEntryStart = pCharEntryEnd + 1;
- }
- }
- }
- // look for the meta data properties
- if (HXR_OK == pReqHeaders->GetPropertyCString("AcceptServerMetaData", pBuffer))
- {
- SafeStrCpy(pszServerMetaData, (char*) pBuffer->GetBuffer(), 256);
- HX_RELEASE(pBuffer);
- // first make sure we have a composit key for "statistics.Player0.ServerMetaData"
- SafeSprintf(buff, MAX_DISPLAY_NAME, "%s.%s", szSMDKey, szServerMetaData);
- regid = m_pRegistry->GetId(buff);
- if (!regid)
- {
- m_pRegistry->AddComp(buff);
- }
- SafeStrCpy(szSMDKey, buff, 256);
- // look for comma delimited entries
- const char* pCharEntryStart = pszServerMetaData;
- const char* pCharEntryEnd = pCharEntryStart;
- while (pCharEntryEnd && *pCharEntryEnd)
- {
- ++pCharEntryEnd;
- if (*pCharEntryEnd == ',' || !*pCharEntryEnd)
- {
- // copy next prop request into buffer
- strncpy(buff, pCharEntryStart, (UINT32)pCharEntryEnd - (UINT32)pCharEntryStart); /* Flawfinder: ignore */
- *(buff+(UINT32)pCharEntryEnd - (UINT32)pCharEntryStart) = ' ';
- // see if this prop is in file header (it should be!)
- if (HXR_OK == pHeader->GetPropertyCString(buff, pBuffer))
- {
- // create new registry entry (if one does not exist)
- SafeSprintf(szRegKeyName, MAX_DISPLAY_NAME, "%s.%s", szSMDKey, buff);
- regid = m_pRegistry->GetId(szRegKeyName);
- if (!regid)
- {
- m_pRegistry->AddStr(szRegKeyName, pBuffer);
- }
- else
- {
- // set new value
- m_pRegistry->SetStrByName(szRegKeyName, pBuffer);
- }
- HX_RELEASE(pBuffer);
- }
- else if (HXR_OK == pHeader->GetPropertyULONG32(buff, ulValue))
- {
- // create new registry entry
- SafeSprintf(szRegKeyName, MAX_DISPLAY_NAME, "%s.%s", szSMDKey, buff);
- regid = m_pRegistry->GetId(szRegKeyName);
- if (!regid)
- {
- m_pRegistry->AddInt(szRegKeyName, ulValue);
- }
- else
- {
- // set new value
- m_pRegistry->SetIntByName(szRegKeyName, ulValue);
- }
- }
- pCharEntryStart = pCharEntryEnd + 1;
- }
- }
- }
- HX_RELEASE(pReqHeaders);
- }
- HX_RELEASE(pRequest);
- }
- HX_RELEASE(pParentName);
- }
- return HXR_OK;
- }
- #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
- HX_RESULT HXSource::SetPlayTimes(UINT32 ulStartTime,
- UINT32 ulEndTime,
- UINT32 ulDelay,
- UINT32 ulDuration)
- {
- m_ulStartTime = ulStartTime;
- m_ulEndTime = ulEndTime;
- /* We do not handle Delay field for now */
- m_ulDelay = ulDelay;
- m_ulRestrictedDuration = ulDuration;
- if (m_ulEndTime > 0)
- {
- m_bCustomEndTime = TRUE;
- }
- else
- {
- m_bCustomEndTime = FALSE;
- }
- return HXR_OK;
- }
- HX_RESULT
- HXSource::UpdatePlayTimes(IHXValues* pValues)
- {
- HX_RESULT rc = HXR_OK;
- char szStart[] = "Start";
- char szEnd[] = "End";
- char szDelay[] = "Delay";
- char szDuration[] = "Duration";
- UINT32 ulStartTime = 0;
- UINT32 ulEndTime = 0;
- UINT32 ulDelay = 0;
- UINT32 ulRestrictedDuration = 0;
- pValues->GetPropertyULONG32(szStart, ulStartTime);
- pValues->GetPropertyULONG32(szEnd, ulEndTime);
- pValues->GetPropertyULONG32(szDelay, ulDelay);
- pValues->GetPropertyULONG32(szDuration, ulRestrictedDuration);
- if (ulStartTime != m_ulStartTime ||
- ulEndTime != m_ulEndTime ||
- ulDelay != m_ulDelay ||
- ulRestrictedDuration != m_ulRestrictedDuration)
- {
- SetPlayTimes(ulStartTime, ulEndTime, ulDelay, ulRestrictedDuration);
- rc = AdjustClipTime();
- }
- return rc;
- }
- ULONG32
- HXSource::GetPerfectPlayTime(void)
- {
- ULONG32 ulCurrentPlayTime = m_pPlayer ? m_pPlayer->GetCurrentPlayTime() : 0;
- ULONG32 result = m_bPerfectPlay ? m_ulPerfectPlayTime : m_ulBufferedPlayTime;
- if (m_ulDuration != 0)
- {
- // mPlaybackLength is in Milliseconds, we want to calculate
- // playback in seconds...
- ULONG32 playbackTimeLeftInClip =
- ((m_ulDuration > ulCurrentPlayTime ? m_ulDuration - ulCurrentPlayTime : 0) /1000)+1;
- /* Perfect Play entire clip ONLY if user has chosen PerfectPlay specifically
- * If we internally go in buffered play mode, always use perfect play time
- * setting.
- */
- if (m_bPerfectPlay)
- {
- if (m_bPerfectPlayEntireClip)
- {
- result = playbackTimeLeftInClip;
- }
- else
- {
- result = min(m_ulPerfectPlayTime, playbackTimeLeftInClip);
- }
- }
- else // if (m_bBufferedPlay)
- {
- result = min(m_ulBufferedPlayTime, playbackTimeLeftInClip);
- }
- }
-
- // check if enough memory is available to handle the result
- if(result > 0)
- {
- // get 50% of the available memory
- ULONG32 maxMemAvail = GetAvailableMemory() / 2;
- ULONG32 bytesPerSecond = m_ulAvgBandwidth/8;
- ULONG32 maxTimeAvail = maxMemAvail/(bytesPerSecond > 0 ? bytesPerSecond : 1);
- // if this is true then we can't buffer the entire clip
- if (maxTimeAvail < result)
- m_bCannotBufferEntireClip = (m_bPerfectPlayEntireClip) ? TRUE : FALSE;
- else
- m_bCannotBufferEntireClip = FALSE;
- result = min(result,maxTimeAvail);
- }
- /* Value now returned in ms. */
- return 1000*(max(result, PERFECTPLAY_MIN_TIME));
- }
- STDMETHODIMP
- HXSource::ReportRebufferStatus(UINT16 uStreamNumber,
- UINT8 unNeeded,
- UINT8 unAvailable)
- {
- STREAM_INFO* pStreamInfo = 0;
- // if (m_bDelayed ||
- // (m_ulDelay > 0 && m_ulDelay > m_pPlayer->GetCurrentPlayTime()))
- if (m_bDelayed)
- {
- return HXR_OK;
- }
- DEBUG_OUT(m_pPlayer, DOL_TRANSPORT, (s, "(%p)ReportRebufferStatus %lu %lu %lu", this, uStreamNumber, unNeeded, unAvailable));
- if (mStreamInfoTable->Lookup((LONG32) uStreamNumber, (void*& )pStreamInfo))
- {
- pStreamInfo->m_unNeeded = unNeeded;
- pStreamInfo->m_unAvailable = unAvailable;
- if (unNeeded > unAvailable)
- {
- // dfprintf("buff", "reportrebufferstatus: %lun", m_pPlayer->GetInternalCurrentPlayTime());
- // g_bRahulLog = TRUE;
- if (m_bFastStart)
- {
- DEBUG_OUT(m_pPlayer, DOL_TRANSPORT, (s, "(%p)ALMOST Turbo OFF ReportRebufferStatus", this));
- //with surestream audio only clips, rarender may report buffering immediately after resume
- if (m_bSureStreamClip)
- {
- if (CALCULATE_ELAPSED_TICKS(m_ulTurboStartActiveTime, HX_GET_TICKCOUNT()) > 1000)
- {
- LeaveFastStart(TP_OFF_BY_REBUFFER);
- DEBUG_OUT(m_pPlayer, DOL_TRANSPORT, (s, "(%p)Turbo OFF ReportRebufferStatus", this));
- }
- }
- else
- {
- LeaveFastStart(TP_OFF_BY_REBUFFER);
- DEBUG_OUT(m_pPlayer, DOL_TRANSPORT, (s, "(%p)Turbo OFF ReportRebufferStatus", this));
- }
- }
- // log rebuffer action
- LogInformation("BUFBEG", NULL);
-
- DoRebuffer();
- }
- else
- {
- m_bRebufferingRequired = IsRebufferRequired();
- if (!m_bRebufferingRequired)
- {
- // log rebuffer action
- LogInformation("BUFEND", NULL);
- }
- }
-
- return HXR_OK;
- }
- return HXR_UNEXPECTED;
- }
- STDMETHODIMP
- HXSource::SetGranularity
- (
- UINT16 uStreamNumber,
- ULONG32 ulGranularity
- )
- {
- STREAM_INFO* pStreamInfo = 0;
- if (mStreamInfoTable->Lookup((LONG32) uStreamNumber, (void*& )pStreamInfo))
- {
- m_pPlayer->SetGranularity(this, uStreamNumber, ulGranularity);
- return HXR_OK;
- }
- else
- {
- return HXR_OK;
- }
- return HXR_UNEXPECTED;
- }
- BOOL
- HXSource::TryResume(void)
- {
- BOOL bResume = FALSE;
- // resume the persistent source ASAP
- if (m_pSourceInfo && m_pSourceInfo->m_bIsPersistentSource)
- {
- m_bDelayed = FALSE;
- bResume = TRUE;
- }
- else if (m_bPaused && m_bDelayed && m_pPlayer &&
- m_pPlayer->CanBeStarted(this, m_pSourceInfo, m_bPartOfNextGroup))
- {
- UINT32 ulCurrentTime = m_pPlayer->GetInternalCurrentPlayTime();
- UINT32 ulStartTime = 0;
- if (m_ulDelay > m_ulPreRollInMs + NETWORK_FUDGE_FACTOR)
- {
- ulStartTime = m_ulDelay - (m_ulPreRollInMs + NETWORK_FUDGE_FACTOR);
- }
- if (ulCurrentTime >= ulStartTime)
- {
- m_bDelayed = FALSE;
- bResume = TRUE;
- }
- if (!m_bIsPreBufferingStarted)
- {
- m_bIsPreBufferingStarted = TRUE;
- bResume = TRUE;
- }
- }
- else if (m_bPrefetch)
- {
- bResume = TRUE;
- }
- if (bResume && CanBeResumed())
- {
- if (m_pSourceInfo)
- {
- m_pSourceInfo->Register();
- }
- m_bResumePending = TRUE;
- }
- return bResume;
- }
- BOOL
- HXSource::IsAnyAudioStream(void)
- {
- IHXAudioPlayer* pAudioPlayer = NULL;
- BOOL bAtLeastOneAudioStream = FALSE;
- if (!m_pPlayer)
- {
- return FALSE;
- }
- m_pPlayer->QueryInterface(IID_IHXAudioPlayer, (void **) &pAudioPlayer);
- UINT16 uNumAudioStreams = pAudioPlayer->GetAudioStreamCount();
- for (UINT16 i = 0; i < uNumAudioStreams && !bAtLeastOneAudioStream; i++)
- {
- IHXAudioStream* pAudioStream = pAudioPlayer->GetAudioStream(i);
- IHXValues* pHeader = pAudioStream->GetStreamInfo();
- pAudioStream->Release();
- if (!pHeader)
- {
- continue;
- }
-
- if (IsAudioStreamFromThisSource(pHeader))
- {
- bAtLeastOneAudioStream = TRUE;
- pHeader->Release();
- break;
- }
- pHeader->Release();
- }
- if (!bAtLeastOneAudioStream)
- {
- IHXValues* pHeader = NULL;
- int nStreamCnt = GetNumStreams();
- ULONG32 ulIsAudioStream = FALSE;
- for (int i=0; i<nStreamCnt && !bAtLeastOneAudioStream; i++)
- {
- GetStreamHeaderInfo(i, pHeader);
- pHeader->GetPropertyULONG32("IsAudioStream", ulIsAudioStream);
- if (ulIsAudioStream)
- {
- bAtLeastOneAudioStream = TRUE;
- }
- HX_RELEASE(pHeader);
- }
- }
- pAudioPlayer->Release();
- return bAtLeastOneAudioStream;
- }
- void
- HXSource::EventReady(CHXEvent* pEvent)
- {
- if (m_pPlayer)
- {
- m_pPlayer->EventReady(this, pEvent);
- }
- }
- BOOL
- HXSource::IsAudioStreamFromThisSource(IHXValues* pAudioHeader)
- {
- BOOL bFound = FALSE;
- CHXMapLongToObj::Iterator ndxStreamIterator = mStreamInfoTable->Begin();
- for (; ndxStreamIterator != mStreamInfoTable->End(); ++ndxStreamIterator)
- {
- STREAM_INFO* pStreamInfo = (STREAM_INFO*) (*ndxStreamIterator);
- if (pStreamInfo->m_pHeader == pAudioHeader)
- {
- bFound = TRUE;
- break;
- }
- }
- return bFound;
- }
- ULONG32
- HXSource::GetAvailableMemory()
- {
- ULONG32 memAvail = 1000000;
- #if defined (__MWERKS__)
- // XXX Hack! We can't call any of the Memory Manager calls at interrupt time so we will have
- // to change this to ask our interrupt safe memory allocator how much memory is free
- memAvail = 1000000;
- #elif defined(_WINCE) && !defined(_WIN32_WCE_EMULATION)
- STORE_INFORMATION stInfo;
- GetStoreInformation(&stInfo);
- memAvail = stInfo.dwFreeSize;
- #elif (_WIN32)
- MEMORYSTATUS status;
- status.dwLength = sizeof(MEMORYSTATUS);
- GlobalMemoryStatus(&status);
- memAvail = status.dwAvailPageFile;
- #elif defined( _WINDOWS)
- memAvail = GetFreeSpace(0);
- #elif defined (_UNIX)
- // XXXX Need to get this to compile.
- memAvail = 1000000;
- #endif
- return memAvail;
- }
- void
- HXSource::ReportError(HX_RESULT theErr)
- {
- if (m_pPlayer)
- {
- m_pPlayer->ReportError(this, theErr);
- }
- }
- HX_RESULT
- HXSource::AdjustClipTime(void)
- {
- HX_RESULT theErr = HXR_OK;
- UINT32 ulOriginalDuration = m_ulDuration;
- UINT32 ulTrackEndTime = 0;
- CHXMapLongToObj::Iterator i;
- BOOL bCustomEndTimeSet = FALSE;
- if (m_bPartOfPrefetchGroup)
- {
- if (m_ulDelay)
- {
- m_ulPrefetchDelay = m_ulDelay;
- m_bDelayed = TRUE;
- AdjustClipBandwidthStats(FALSE);
- DoPause();
- }
- m_ulEndTime = 0;
- m_bCustomEndTime = FALSE;
- goto cleanup;
- }
-
- /* For a live stream, the only qualifiers that make sense
- * are Duration and Delay. All other qualifiers should be made 0
- */
- if (mLiveStream)
- {
- m_ulStartTime = 0;
- if (!m_bRestrictedLiveStream)
- {
- m_ulEndTime = 0;
- }
- }
- for (i = mStreamInfoTable->Begin(); i != mStreamInfoTable->End(); ++i)
- {
- STREAM_INFO* pStreamInfo = (STREAM_INFO*) (*i);
- ulTrackEndTime = 0;
- HX_RESULT hrTemp = pStreamInfo->m_pHeader->GetPropertyULONG32("EndTime", ulTrackEndTime);
- if (HXR_OK == hrTemp && !m_bCustomEndTime)
- {
- if (m_ulEndTime < ulTrackEndTime)
- {
- m_ulEndTime = ulTrackEndTime;
- }
- pStreamInfo->m_bCustomEndTime = TRUE;
- }
- else if (m_bCustomEndTime)
- {
- ulTrackEndTime = m_ulEndTime;
- pStreamInfo->m_bCustomEndTime = TRUE;
- }
- if (ulTrackEndTime > 0 && !mLiveStream)
- {
- pStreamInfo->m_pHeader->SetPropertyULONG32("TrackEndTime",
- ulTrackEndTime);
- bCustomEndTimeSet = TRUE;
- }
- }
-
- // if max. duration is set on this source
- if (m_pSourceInfo &&
- m_pSourceInfo->m_ulMaxDuration)
- {
- if (m_ulRestrictedDuration)
- {
- if (m_ulRestrictedDuration > m_pSourceInfo->m_ulMaxDuration)
- {
- m_ulRestrictedDuration = m_pSourceInfo->m_ulMaxDuration;
- }
- }
- else if (m_ulDuration)
- {
- if (m_ulDuration > m_pSourceInfo->m_ulMaxDuration)
- {
- m_ulRestrictedDuration = m_pSourceInfo->m_ulMaxDuration;
- }
- }
- }
- // By default, we always set the end time to be the duration of the clip,
- // but do not set end time if it was manually specified.
- if (!bCustomEndTimeSet && !mLiveStream)
- {
- m_ulEndTime = m_ulDuration;
- }
- /* Check if there is any end time */
- if ((m_ulEndTime < m_ulDuration) || m_bRestrictedLiveStream)
- {
- m_ulDuration = m_ulEndTime;
- }
-
- /* Is "Delay" specified too? */
- if (m_ulDelay > 0)
- {
- /* Increase duration of this clip */
- m_ulDuration += m_ulDelay;
- UINT32 ulStartTime = 0;
- if (m_ulDelay > m_ulPreRollInMs + NETWORK_FUDGE_FACTOR)
- {
- ulStartTime = m_ulDelay - (m_ulPreRollInMs + NETWORK_FUDGE_FACTOR);
- }
- // no need to pause delayed persistent component since Pause() will be called
- // on actual tracks' AdjustClipTime() if necessary
- if (m_pSourceInfo && !m_pSourceInfo->m_bIsPersistentSource)
- {
- m_bDelayed = TRUE;
- AdjustClipBandwidthStats(FALSE);
- DoPause();
- }
- }
- if (m_ulStartTime > 0) /* reduce duration by start time amount */
- {
- if (m_ulDuration > m_ulStartTime)
- {
- m_ulDuration -= m_ulStartTime;
- }
- else
- {
- /* This is bad case. We consider it invalid */
- m_ulDuration = 0;
- }
- }
- /* We now allow to increase the default duration of the clip */
- if (m_ulRestrictedDuration > 0)
- {
- m_ulDuration = m_ulRestrictedDuration + m_ulDelay;
- if (mLiveStream && !m_bRestrictedLiveStream)
- {
- m_bRestrictedLiveStream = TRUE;
- m_ulEndTime = m_ulRestrictedDuration + m_ulStartTime;
- }
-
- if (m_ulEndTime > m_ulRestrictedDuration + m_ulStartTime)
- {
- m_ulEndTime = m_ulRestrictedDuration + m_ulStartTime;
- }
- }
- // orig duration is active duration for this source -- time for which
- // this source lasts.
- if (m_ulDuration > m_ulDelay)
- {
- m_ulOriginalDuration = m_ulDuration - m_ulDelay;
- }
- else
- {
- m_ulOriginalDuration = 0;
- }
- if (m_pURL &&
- rtspProtocol == m_pURL->GetProtocol() &&
- m_llLastExpectedPacketTime != m_ulEndTime &&
- !m_bFirstResume)
- {
- m_bRTSPRuleFlagWorkAround = TRUE;
- }
- /* If we receive a packet after this stream, we consider the stream to be done */
- m_llLastExpectedPacketTime = CAST_TO_INT64 m_ulEndTime;
- // Seek to the starting position only if the source
- // has not been resumed yet
- if (m_ulStartTime > 0 && m_bFirstResume)
- {
- /* We will add m_ulStartTime in DoSeek() call*/
- theErr = DoSeek(0);
- }
- /* Update stream durations if required */
- for (i = mStreamInfoTable->Begin(); i != mStreamInfoTable->End(); ++i)
- {
- STREAM_INFO* pStreamInfo = (STREAM_INFO*) (*i);
- if (m_ulStartTime > 0)
- {
- pStreamInfo->m_pHeader->SetPropertyULONG32("TrackStartTime",
- m_ulStartTime);
- }
-
- if (m_ulEndTime > 0 &&
- !mLiveStream &&
- HXR_OK != pStreamInfo->m_pHeader->GetPropertyULONG32("TrackEndTime",
- ulTrackEndTime))
- {
- pStreamInfo->m_pHeader->SetPropertyULONG32("TrackEndTime",
- m_ulEndTime);
- }
- if (ulOriginalDuration != m_ulDuration)
- {
- pStreamInfo->m_ulDuration = m_ulDuration;
- pStreamInfo->m_pHeader->SetPropertyULONG32("Duration",
- pStreamInfo->m_ulDuration);
- }
- if (m_ulDelay > 0)
- {
- pStreamInfo->m_pHeader->SetPropertyULONG32("Delay", m_ulDelay);
- }
- }
- //{FILE* f1 = ::fopen("d:\temp\url.txt", "a+"); ::fprintf(f1, "%p %s %lu %lun", this, m_pszURL, m_ulDelay, m_ulDuration);::fclose(f1);}
- cleanup:
- m_bClipTimeAdjusted = TRUE;
- return theErr;
- }
- void
- HXSource::GenerateFakeLostPacket(CHXEvent*& theEvent)
- {
- IHXPacket* pPacket = theEvent->GetPacket();
- CHXPacket* pLostPacket = new CHXPacket;
- pLostPacket->AddRef();
- pLostPacket->Set(0, 0, pPacket->GetStreamNumber(), 0, 0);
- pLostPacket->SetAsLost();
- /* Create a new event with lost packet */
- CHXEvent* pEvent = new CHXEvent(pLostPacket);
- pEvent->SetTimeStartPos(theEvent->GetTimeStartPos());
- pEvent->SetTimeOffset(theEvent->GetTimeOffset());
- pEvent->SetPreSeekEvent(theEvent->IsPreSeekEvent());
- pLostPacket->Release();
- delete theEvent;
- theEvent = pEvent;
- }
- char*
- HXSource::GetAltURL(BOOL& bDefault)
- {
- #if defined(HELIX_FEATURE_ALT_URL)
- char* pAltURL = NULL;
- if (!m_pURL || m_bInitialized)
- {
- goto cleanup;
- }
- pAltURL = m_pURL->GetAltURL(bDefault);
- cleanup:
- return pAltURL;
- #else
- return NULL;
- #endif /* HELIX_FEATURE_ALT_URL */
- }
- HX_RESULT
- HXSource::SetRequest(const CHXURL* pURL, BOOL bAltURL)
- {
- HX_RESULT hr = HXR_OK;
- IHXValues* pValues = NULL;
- IHXValues* pValuesInRequest = NULL;
- IHXGroup* pGroup = NULL;
- IHXGroup2* pGroup2 = NULL;
- IHXGroupManager* pGroupManager = NULL;
- HX_RELEASE(m_pRequest);
- if (m_pPlayer)
- {
- m_pPlayer->GetActiveRequest(m_pRequest);
- if (m_pRequest)
- {
- m_pPlayer->ResetActiveRequest();
- }
- }
- #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
- if (m_pPlayer && m_pSourceInfo)
- {
- if (HXR_OK == m_pPlayer->QueryInterface(IID_IHXGroupManager, (void**)&pGroupManager))
- {
- if (HXR_OK == pGroupManager->GetGroup(m_pSourceInfo->m_uGroupID, pGroup))
- {
- if (HXR_OK == pGroup->QueryInterface(IID_IHXGroup2, (void**)&pGroup2))
- {
- pGroup2->GetTrack2(m_pSourceInfo->m_uTrackID, pValues, pValuesInRequest);
- UINT32 ulValue = 0;
- char szDuration[128] = {0}; /* Flawfinder: ignore */
- IHXBuffer* pBuffer = NULL;
- if (pValues && HXR_OK == pValues->GetPropertyULONG32("Duration", ulValue))
- {
- if (!pValuesInRequest)
- {
- pValuesInRequest = new CHXHeader();
- if( pValuesInRequest )
- {
- pValuesInRequest->AddRef();
- }
- else
- {
- hr = HXR_OUTOFMEMORY;
- }
- }
- if (pValuesInRequest)
- {
- SafeSprintf (szDuration, 128, "%lu", ulValue); /* Flawfinder: ignore */
- pBuffer = new CHXBuffer();
- pBuffer->AddRef();
- pBuffer->Set((UCHAR*)szDuration, strlen(szDuration) + 1);
- pValuesInRequest->SetPropertyCString("Duration", pBuffer);
- HX_RELEASE(pBuffer);
- }
- }
- }
- HX_RELEASE(pGroup2);
- }
- HX_RELEASE(pGroup);
- }
- HX_RELEASE(pGroupManager);
- }
- #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
- IHXRegistry* pRegistry = NULL;
- m_pEngine->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
- hr = ::SetRequest(pURL->GetEscapedURL(), bAltURL, m_pPreferences, pRegistry, pValuesInRequest, m_pRequest);
- HX_RELEASE(pValues);
- HX_RELEASE(pValuesInRequest);
- HX_RELEASE(pRegistry);
- #if defined(HELIX_FEATURE_RECORDCONTROL)
- if(hr == HXR_OK && pURL->GetProtocol() != fileProtocol)
- {
- if(!m_pRecordControl)
- {
- m_pRecordControl = new HXRecordControl((IHXPlayer*)m_pPlayer, (IHXStreamSource*)this);
- if(m_pRecordControl)
- {
- m_pRecordControl->AddRef();
- if(m_pRecordControl->IsValid())
- m_bPlayFromRecordControl = m_pRecordControl->CanGetPackets();
- else
- HX_RELEASE(m_pRecordControl);
- }
- }
- if(m_pRecordControl)
- {
- m_pRecordControl->SetSource((IHXStreamSource*)this);
- }
- }
- #endif /* HELIX_FEATURE_RECORDCONTROL */
- return hr;
- }
- void
- HXSource::UpdateDuration(UINT32 ulDuration)
- {
- CHXSimpleList* pRepeatList = m_pSourceInfo->GetRepeatList();
- // ulDuration excludes the delay time
- if (pRepeatList &&
- ulDuration >= (m_ulDuration - m_ulDelay))
- {
- m_pSourceInfo->m_ulTotalTrackDuration = ulDuration + m_ulDelay;
- if (m_pSourceInfo->m_pPeerSourceInfo)
- {
- m_pSourceInfo->m_pPeerSourceInfo->m_ulTotalTrackDuration = m_pSourceInfo->m_ulTotalTrackDuration;
- }
- }
- else
- {
- m_ulOriginalDuration = m_ulRestrictedDuration = ulDuration;
- AdjustClipTime();
- m_pSourceInfo->UpdateDuration(m_ulDuration);
- }
- }
- void
- HXSource::UpdateDelay(UINT32 ulDelay)
- {
- m_ulDelay = ulDelay;
- AdjustClipTime();
- m_pSourceInfo->UpdateDelay(m_ulDelay);
- }
- void
- HXSource::InitialBufferingDone(void)
- {
- m_bInitialBuffering = FALSE;
- // resume if we satisfy the initial preroll AND we have issued
- // rebuffer
- // note: IsRebufferRequired() should return FALSE!!
- if (m_bRebufferingRequired)
- {
- m_bRebufferingRequired = IsRebufferRequired();
- HX_ASSERT(!m_bRebufferingRequired);
- }
- return;
- }
- void
- HXSource::DoRebuffer(void)
- {
- m_bRebufferingRequired = TRUE;
- if (m_pPlayer)
- {
- m_pPlayer->InternalPause();
- ReBuffer();
- }
- return;
- }
- BOOL
- HXSource::IsRebufferRequired(void)
- {
- BOOL bResult = FALSE;
- STREAM_INFO* pStreamInfo = NULL;
- // Check if all streams are doing OK
- for (CHXMapLongToObj::Iterator ndxStrm = mStreamInfoTable->Begin();
- ndxStrm != mStreamInfoTable->End(); ++ndxStrm)
- {
- pStreamInfo = (STREAM_INFO*) (*ndxStrm);
-
- if (pStreamInfo->m_unNeeded > pStreamInfo->m_unAvailable)
- {
- bResult = TRUE;
- break;
- }
- }
- return bResult;
- }
- BOOL
- HXSource::IsRebufferDone(void)
- {
- BOOL bResult = TRUE;
- if (m_pSourceInfo)
- {
- bResult = m_pSourceInfo->IsRebufferDone();
- }
- return bResult;
- }
- void
- HXSource::ScheduleProcessCallback()
- {
- if (m_pSourceInfo)
- {
- m_pSourceInfo->ScheduleProcessCallback();
- }
- }
- #if defined(HELIX_FEATURE_HYPER_NAVIGATE)
- /************************************************************************
- * Method:
- * IHXHyperNavigate::GoToURL
- * Purpose:
- * Acts as a proxy for actual hypernavigate interface.
- * Is used to convert any relative URLs to absolute URLs
- */
- STDMETHODIMP
- HXSource::GoToURL(const char* pURL, const char* pTarget)
- {
- return Execute(pURL, pTarget, NULL, NULL, NULL);
- }
- /************************************************************************
- * Method:
- * IHXHyperNavigate2::Execute
- * Purpose:
- *
- * Parameters:
- * pURL: URL (absolute or relative)
- * pTargetInstance:
- * pTargetApplication:
- * pTargetRegion:
- * pParams:
- */
- STDMETHODIMP
- HXSource::Execute(const char* pURL,
- const char* pTargetInstance,
- const char* pTargetApplication,
- const char* pTargetRegion,
- IHXValues* pParams)
- {
- HX_RESULT theErr = HXR_OK;
- CHXString newURL = pURL;
- // pURL = "rogers.rt";
- // if (pTargetInstance &&
- // stricmp(pTargetInstance, "_player") == 0 &&
- if (ShouldConvert(pTargetInstance) &&
- pURL &&
- strnicmp(pURL, URL_COMMAND, sizeof(URL_COMMAND) - 1) != 0 )
- {
- CHXURL urlObj(pURL);
- IHXValues* pHeader = urlObj.GetProperties();
- IHXBuffer* pBuffer = NULL;
- if(pHeader &&
- m_pszURL &&
- HXR_OK != pHeader->GetPropertyBuffer(PROPERTY_SCHEME, pBuffer))
- {
- // relative URL
- // if it starts with '/', make it relative to the root of
- // the URL prefix
- CHXString urlPrefix, urlRoot;
- char* pURLFragment = NULL;
- theErr = CHXURL::GeneratePrefixRootFragment(m_pszURL, urlPrefix, urlRoot, pURLFragment);
- HX_VECTOR_DELETE(pURLFragment);
- if (!theErr)
- {
- if(*pURL == '/')
- {
- newURL = urlRoot + pURL;
- }
- else
- {
- newURL = urlPrefix + pURL;
- }
- }
- }
- HX_RELEASE(pBuffer);
- HX_RELEASE(pHeader);
- }
-
- AddRef();
- HX_ASSERT(m_pPlayer && m_pPlayer->m_pHyperNavigate);
- if (m_pPlayer && m_pPlayer->m_pHyperNavigate)
- {
- theErr = m_pPlayer->m_pHyperNavigate->ExecuteWithContext(newURL,
- pTargetInstance, pTargetApplication, pTargetRegion,
- pParams, (IUnknown*) (IHXStreamSource*) this);
- }
- Release();
- return theErr;
- }
- #endif /* defined(HELIX_FEATURE_HYPER_NAVIGATE) */
- STDMETHODIMP
- HXSource::GetTotalBuffering(UINT16 uStreamNumber,
- REF(INT64) llLowestTimestamp,
- REF(INT64) llHighestTimestamp,
- REF(UINT32) ulNumBytes,
- REF(BOOL) bDone)
- {
- HX_RESULT res = HXR_NO_DATA;
-
- llLowestTimestamp = 0;
- llHighestTimestamp = 0;
- ulNumBytes = 0;
- bDone = FALSE;
- STREAM_INFO* pStreamInfo;
- if (mStreamInfoTable->Lookup((LONG32) uStreamNumber, (void*& )pStreamInfo))
- {
- HXBufferingState& bufState = pStreamInfo->BufferingState();
- BOOL bUseTransportStats = FALSE;
- INT64 llTransportLowTS = 0;
- INT64 llTransportHighTS = 0;
- UINT32 ulTransportBytes = 0;
- BOOL bTransportDone = FALSE;
- if (!IsLocalSource() &&
- (HXR_OK == GetCurrentBuffering(uStreamNumber,
- llTransportLowTS,
- llTransportHighTS,
- ulTransportBytes,
- bTransportDone)))
- {
- bufState.UpdateTransportStats(llTransportLowTS,
- llTransportHighTS,
- ulTransportBytes,
- bTransportDone);
- bUseTransportStats = TRUE;
- // Update bDone with what the transport says.
- bDone = bTransportDone;
- }
- res = bufState.GetBufferingStats(llLowestTimestamp,
- llHighestTimestamp,
- ulNumBytes,
- bUseTransportStats);
- }
- return res;
- }
- /*
- * All relative URLs are converted to absolute URLs unless the
- * original request (ram/smil) passed in OpenRequest/OpenURL()
- * is a mem: URL AND the target is not _player.
- *
- * This fixes relative URLs being hurled to the browser using events
- * come from the same location as the .ram file. (Broadcase usage case)
- * PR 31352
- *
- * This also fixes content on CD-ROMs where relative URLs being hurled
- * to the browser using events come from the same location as
- * the .rm file in which they are merged.
- * PR 23489
- */
- BOOL HXSource::ShouldConvert(const char* pTargetInstance)
- {
- if (pTargetInstance &&
- stricmp(pTargetInstance, "_player") == 0)
- {
- return TRUE;
- }
-
- const char* pPlayerURL = NULL;
- IHXRequest* pPlayerRequest = NULL;
- if (m_pPlayer)
- {
- m_pPlayer->GetRequest(pPlayerRequest);
- if (pPlayerRequest)
- {
- pPlayerRequest->GetURL(pPlayerURL);
- }
- }
- HX_RELEASE(pPlayerRequest);
- if (pPlayerURL && ::strncasecmp(pPlayerURL, "mem:", 4) == 0)
- {
- return FALSE;
- }
- return TRUE;
- }
- void
- HXSource::MergeUpgradeRequest(BOOL bAddDefault /*= FALSE*/, char* pUpgradeString /* = NULL*/)
- {
- #if defined(HELIX_FEATURE_AUTOUPGRADE)
- if (m_pPlayer &&
- bAddDefault &&
- (!m_pUpgradeCollection || m_pUpgradeCollection->GetCount() == 0))
- {
- if (!m_pUpgradeCollection)
- {
- m_pUpgradeCollection = new HXUpgradeCollection;
- }
- if (!pUpgradeString)
- {
- pUpgradeString = "Missing Component";
- }
- IHXBuffer* pPluginID = (IHXBuffer*) new CHXBuffer;
- pPluginID->AddRef();
- pPluginID->Set((const UINT8*)pUpgradeString, strlen(pUpgradeString) + 1);
- m_pUpgradeCollection->Add(eUT_Required, pPluginID, 0, 0);
- pPluginID->Release();
- }
- if (m_pPlayer && m_pUpgradeCollection && m_pUpgradeCollection->GetCount() > 0)
- {
- UINT32 ulCount = m_pUpgradeCollection->GetCount();
- IHXUpgradeCollection* pPlayerUpgrade;
- m_pPlayer->QueryInterface(IID_IHXUpgradeCollection, (void**) &pPlayerUpgrade);
- for (UINT32 i = 0; i < ulCount; i++)
- {
- HXUpgradeType upgradeType;
- IHXBuffer* pPluginId = (IHXBuffer*) new CHXBuffer;
- UINT32 majorVersion;
- UINT32 minorVersion;
- pPluginId->AddRef();
- // GetAt is a non-COM like API. It expects pPluginID to be allocated by the user
- // and does not perform an addref either!
- m_pUpgradeCollection->GetAt(i, upgradeType, pPluginId, majorVersion, minorVersion);
- pPlayerUpgrade->Add(upgradeType, pPluginId, majorVersion, minorVersion);
- pPluginId->Release();
- }
- pPlayerUpgrade->Release();
- m_pUpgradeCollection->RemoveAll();
- }
- #endif /* HELIX_FEATURE_AUTOUPGRADE */
- }
- void
- HXSource::ClearUpgradeRequest()
- {
- #if defined(HELIX_FEATURE_AUTOUPGRADE)
- if (m_pUpgradeCollection)
- {
- m_pUpgradeCollection->RemoveAll();
- }
- #endif /* HELIX_FEATURE_AUTOUPGRADE */
- }
- void
- HXSource::EnterPrefetch(PrefetchType prefetchType, UINT32 ulPrefetchValue)
- {
- m_bPrefetch = TRUE;
- m_prefetchType = prefetchType;
- m_ulPrefetchValue = ulPrefetchValue;
- return;
- }
- void
- HXSource::LeavePrefetch(void)
- {
- m_bPrefetch = FALSE;
- // send prefetch notification so that SMIL
- // renderer can resolve the duration on this prefetch track
- if (m_pSourceInfo)
- {
- m_pPlayer->PrefetchTrackDone(m_pSourceInfo->m_uGroupID,
- m_pSourceInfo->m_uTrackID,
- HXR_OK);
- }
- return;
- }
- void
- HXSource::SetSoundLevel(UINT16 uSoundLevel, BOOL bReflushAudioDevice)
- {
- #if defined(HELIX_FEATURE_SMIL_SOUNDLEVEL)
- CHXAudioPlayer* pAudioPlayer = NULL;
- CHXAudioStream* pCHXAudioStream = NULL;
- CHXSimpleList* pAudioStreamList = NULL;
- if (!m_pPlayer)
- {
- goto cleanup;
- }
- pAudioPlayer = m_pPlayer->GetAudioPlayer();
- if (!pAudioPlayer)
- {
- goto cleanup;
- }
- pAudioPlayer->AddRef();
- if (HXR_OK == CollectAudioStreams(pAudioStreamList) && pAudioStreamList)
- {
- pAudioPlayer->SetSoundLevel(pAudioStreamList, uSoundLevel, bReflushAudioDevice);
- ReleaseAudioStreams(pAudioStreamList);
- HX_DELETE(pAudioStreamList);
- }
- HX_RELEASE(pAudioPlayer);
- cleanup:
- #endif /* HELIX_FEATURE_SMIL_SOUNDLEVEL */
- return;
- }
- void
- HXSource::SetAudioDeviceReflushHint(void)
- {
- #if defined(HELIX_FEATURE_SOUNDLEVEL)
- CHXAudioPlayer* pAudioPlayer = NULL;
- CHXSimpleList* pAudioStreamList = NULL;
- if (!m_pPlayer)
- {
- goto cleanup;
- }
- pAudioPlayer = m_pPlayer->GetAudioPlayer();
- if (!pAudioPlayer)
- {
- goto cleanup;
- }
- pAudioPlayer->AddRef();
- if (HXR_OK == CollectAudioStreams(pAudioStreamList) && pAudioStreamList)
- {
- pAudioPlayer->ManageAudioStreams(pAudioStreamList, CHXAudioPlayer::STR_SETHINT);
- ReleaseAudioStreams(pAudioStreamList);
- HX_DELETE(pAudioStreamList);
- }
- HX_RELEASE(pAudioPlayer);
- cleanup:
- #endif /* HELIX_FEATURE_SOUNDLEVEL */
- return;
- }
- void
- HXSource::LeaveFastStart(TurboPlayOffReason leftReason)
- {
- m_turboPlayStats.tpOffReason = leftReason;
- m_bFastStart = FALSE;
- }
- void
- HXSource::DeleteAllEvents()
- {
- if (m_PacketBufferList.GetCount() > 0)
- {
- LISTPOSITION pos = m_PacketBufferList.GetHeadPosition();
- while (pos != NULL)
- {
- CHXEvent* pTempEvent = (CHXEvent*) m_PacketBufferList.GetNext(pos);
- delete pTempEvent;
- }
- m_PacketBufferList.RemoveAll();
- }
- }
- void
- HXSource::SetMinimumPreroll(ULONG32 ulMinimumAudioPreroll, ULONG32 ulMinimumStartingPreroll)
- {
- UINT32 ulTotalMinimumPreroll = 0;
- if (m_pPlayer)
- {
- // get the user-set minimum preroll
- m_pPlayer->GetMinimumPreroll(ulTotalMinimumPreroll);
- }
- if (IsAnyAudioStream())
- {
- m_ulPreRollInMs += ulMinimumAudioPreroll;
- }
- if (m_ulPreRollInMs < ulTotalMinimumPreroll)
- {
- m_ulPreRollInMs = ulTotalMinimumPreroll;
- }
- DEBUG_OUT(m_pPlayer, DOL_TRANSPORT, (s, "(%p)Preroll: %lu MinPreroll %lu MinAudioPreroll %lu", this, m_ulPreRollInMs, ulTotalMinimumPreroll, ulMinimumStartingPreroll));
- m_pBufferManager->SetMinimumPreroll(IsLocalSource() | m_bPerfectPlay,
- ulTotalMinimumPreroll,
- ulMinimumStartingPreroll);
- }
- HX_RESULT
- HXSource::SendHeaderToRecordControl(BOOL bFileHeader, IHXValues* pHeader)
- {
- #if defined(HELIX_FEATURE_RECORDCONTROL)
- HX_RESULT nResult = HXR_OK;
- if(m_pRecordControl && pHeader)
- {
- if(bFileHeader)
- nResult = m_pRecordControl->OnFileHeader(pHeader);
- else
- nResult = m_pRecordControl->OnStreamHeader(pHeader);
- if(nResult != HXR_OK)
- {
- m_bPlayFromRecordControl = FALSE;
- if(nResult != HXR_RECORD)
- HX_RELEASE(m_pRecordControl);
- }
- }
- return nResult;
- #else
- return HXR_NOTIMPL;
- #endif /* HELIX_FEATURE_RECORDCONTROL */
- }
- void
- HXSource::ProcessFileHeader(void)
- {
- UINT32 bNonSeekAble = 0;
- IHXBuffer* pTitle = NULL;
- IHXBuffer* pAuthor = NULL;
- IHXBuffer* pCopyright = NULL;
- IHXBuffer* pAbstract = NULL;
- IHXBuffer* pDescription = NULL;
- IHXBuffer* pKeywords = NULL;
- IHXValues* pValues = NULL;
- if (m_pURL)
- {
- pValues = m_pURL->GetOptions();
- }
- // retrieve the TAC from the URL
- if (pValues)
- {
- pValues->GetPropertyBuffer("Title", pTitle);
- pValues->GetPropertyBuffer("Author", pAuthor);
- pValues->GetPropertyBuffer("Copyright", pCopyright);
- pValues->GetPropertyBuffer("Abstract", pAbstract);
- pValues->GetPropertyBuffer("Description", pDescription);
- pValues->GetPropertyBuffer("Keywords", pKeywords);
- //#define LOSS_HACK
- #ifdef LOSS_HACK
- UINT32 ulLoss = 0;
- if (HXR_OK == pValues->GetPropertyULONG32("Loss", ulLoss))
- {
- m_ulLossHack = ulLoss;
- /* Initialize random number generator */
- ::srand((unsigned int) HX_GET_TICKCOUNT());
- }
- #endif /*LOSS_HACK*/
- }
- if (m_pFileHeader)
- {
- if (!pTitle) m_pFileHeader->GetPropertyBuffer("Title", pTitle);
- if (!pAuthor) m_pFileHeader->GetPropertyBuffer("Author", pAuthor);
- if (!pCopyright) m_pFileHeader->GetPropertyBuffer("Copyright", pCopyright);
- if (!pDescription) m_pFileHeader->GetPropertyCString("Description", pDescription);
- if (!pAbstract) m_pFileHeader->GetPropertyCString("Abstract", pAbstract);
- if (!pKeywords) m_pFileHeader->GetPropertyCString("Keywords", pKeywords);
- m_pFileHeader->GetPropertyULONG32("NonSeekable", bNonSeekAble);
- m_bNonSeekable = bNonSeekAble ? TRUE : FALSE;
-
- m_pFileHeader->GetPropertyULONG32("StreamCount",m_ulStreamHeadersExpected);
-
- HX_ASSERT(mStreamInfoTable->IsEmpty() == TRUE);
- if (mStreamInfoTable->IsEmpty() && m_ulStreamHeadersExpected > 0 &&
- m_ulStreamHeadersExpected < mStreamInfoTable->GetHashTableSize())
- {
- mStreamInfoTable->InitHashTable(m_ulStreamHeadersExpected);
- }
- }
- #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
- if (m_pStats)
- {
- if (pTitle && m_pStats->m_pTitle)
- {
- m_pStats->m_pTitle->SetStr((char*)(pTitle->GetBuffer()));
- }
- if (pAuthor && m_pStats->m_pAuthor)
- {
- m_pStats->m_pAuthor->SetStr((char*)(pAuthor->GetBuffer()));
- }
- if (pCopyright && m_pStats->m_pCopyright)
- {
- m_pStats->m_pCopyright->SetStr((char*)(pCopyright->GetBuffer()));
- }
- if (pAbstract && m_pStats->m_pAbstract)
- {
- m_pStats->m_pAbstract->SetStr((char*)(pAbstract->GetBuffer()));
- }
-
- if (pDescription && m_pStats->m_pDescription)
- {
- m_pStats->m_pDescription->SetStr((char*)(pDescription->GetBuffer()));
- }
- if (pKeywords && m_pStats->m_pKeywords)
- {
- m_pStats->m_pKeywords->SetStr((char*)(pKeywords->GetBuffer()));
- }
- }
- CopyMetaDataToRegistry(m_pFileHeader);
- #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
- m_bReceivedHeader = TRUE;
- HX_RELEASE(pTitle);
- HX_RELEASE(pAuthor);
- HX_RELEASE(pCopyright);
- HX_RELEASE(pAbstract);
- HX_RELEASE(pDescription);
- HX_RELEASE(pKeywords);
- HX_RELEASE(pValues);
- return;
- }
- static BOOL GetHeaderBOOL(IHXValues* pHeader, const char* pKey)
- {
- BOOL bRet = FALSE;
- ULONG32 ulTemp = 0;
- if ((HXR_OK == pHeader->GetPropertyULONG32(pKey, ulTemp)) && ulTemp)
- {
- bRet = TRUE;
- }
- return bRet;
- }
- HX_RESULT
- HXSource::ProcessStreamHeaders(IHXValues* pHeader, STREAM_INFO*& pStreamInfo)
- {
- HX_RESULT rc = HXR_OK;
- UINT32 ulStreamNumber = 0;
- UINT32 ulAvgBitRate = 0;
- UINT32 ulAvgPacketSize = 0;
- UINT32 ulPreroll = 0;
- ULONG32 ulPredata = 0;
- UINT32 ulDuration = 0;
- UINT32 ulTemp = 0;
- void* lTmp = NULL;
- pStreamInfo = NULL;
- if (!pHeader)
- {
- rc = HX_INVALID_HEADER;
- goto cleanup;
- }
- // Use file header for default duration
- if (m_pFileHeader)
- {
- m_pFileHeader->GetPropertyULONG32("Duration", ulDuration);
- if (!m_ulDuration && ulDuration)
- {
- m_ulDuration = ulDuration;
- ulDuration = 0;
- }
- }
- pHeader->GetPropertyULONG32("StreamNumber", ulStreamNumber);
- pHeader->GetPropertyULONG32("AvgBitRate", ulAvgBitRate);
- pHeader->GetPropertyULONG32("AvgPacketSize", ulAvgPacketSize);
- pHeader->GetPropertyULONG32("Preroll", ulPreroll);
- pHeader->GetPropertyULONG32("Predata", ulPredata);
- pHeader->GetPropertyULONG32("Duration", ulDuration);
- if (mStreamInfoTable->Lookup((LONG32) ulStreamNumber, (void *&) lTmp))
- {
- // a header with this stream number already exists..
- rc = HX_INVALID_HEADER;
- goto cleanup;
- }
- // max preroll
- if (m_ulPreRollInMs < ulPreroll)
- {
- m_ulPreRollInMs = ulPreroll;
- }
- m_ulAvgBandwidth += ulAvgBitRate;
- // max duration...
- if (m_ulDuration < ulDuration)
- {
- m_ulDuration = ulDuration;
- }
- pStreamInfo = new STREAM_INFO;
- if (!pStreamInfo)
- {
- rc = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- pStreamInfo->m_pHeader = pHeader;
- pStreamInfo->m_pHeader->AddRef();
- pStreamInfo->m_bCustomEndTime = FALSE;
- pStreamInfo->m_bSrcStreamDone = FALSE;
- pStreamInfo->m_bSrcStreamFillingDone = FALSE;
- pStreamInfo->m_bPacketRequested = FALSE;
-
- pStreamInfo->m_uStreamNumber = (UINT16) ulStreamNumber;
- pStreamInfo->m_ulDuration = ulDuration;
- pStreamInfo->BufferingState().OnStreamHeader(
- ulPreroll,
- ulPredata,
- GetHeaderBOOL(pHeader, "PreDataAtStart"),
- GetHeaderBOOL(pHeader, "PreDataAfterSeek"),
- GetHeaderBOOL(pHeader, "PrerollAtStart"),
- GetHeaderBOOL(pHeader, "PrerollAfterSeek"),
- ulAvgBitRate);
- mStreamInfoTable->SetAt(ulStreamNumber, (void *) pStreamInfo);
- cleanup:
- return rc;
- }
- HX_RESULT HXSource::OnTimeSync(ULONG32 ulCurrentTime)
- {
- HX_RESULT res = HXR_OK;
- for (CHXMapLongToObj::Iterator i = mStreamInfoTable->Begin();
- i != mStreamInfoTable->End(); ++i)
- {
- STREAM_INFO* pStreamInfo = (STREAM_INFO*) (*i);
- pStreamInfo->BufferingState().OnTimeSync(ulCurrentTime);
- }
- return res;
- }