📄 hxplay.cpp
字号:
#endif
theErr = m_pAudioPlayer->Setup(m_ulLowestGranularity);
if (theErr)
{
SetLastError(theErr);
}
if (!theErr)
{
m_bPostSetupToBeDone = TRUE;
}
return theErr;
}
HX_RESULT
HXPlayer::PrepareAudioPlayer()
{
return HXR_OK;
}
HX_RESULT HXPlayer::ProcessIdle(void)
{
if ((!m_bInitialized || m_bPostSetupToBeDone ) && m_pEngine->AtInterruptTime())
{
return HXR_OK;
}
if (m_bCoreLocked)
{
SchedulePlayer();
return HXR_OK;
}
m_pCoreMutex->Lock();
#if 0
#if defined(_WIN32) && defined(_DEBUG)
GetChangesToWorkingSet();
#endif
#endif
m_bCoreLocked = TRUE;
HX_RESULT theErr = HXR_OK;
BOOL bIsBuffering = FALSE;
UINT16 uLowestBuffering = 100;
SourceInfo* pSourceInfo = NULL;
RendererInfo* pRendInfo = NULL;
IHXRenderer* pRenderer = NULL;
BOOL bDone = FALSE;
BOOL bIsFirst = TRUE;
BOOL bReadyToUpgrade = TRUE;
BOOL bSuppressErrorReporting = FALSE;
UINT32 ulNumStreamsToBeFilled = 0;
UINT32 ulLoopEntryTime = 0;
UINT16 unStatusCode = 0;
UINT16 unPercentDone = 0;
IHXBuffer* pStatusDesc = NULL;
CHXMapPtrToPtr::Iterator ndxSource;
CHXMapLongToObj::Iterator ndxRend;
if (m_bIsDone || m_bSetupToBeDone)
{
goto exitRoutine;
}
#ifdef _MACINTOSH
/* check InternalPause() for details */
if (m_bPendingAudioPause && !m_pEngine->AtInterruptTime())
{
m_pAudioPlayer->Pause();
}
#endif
ndxSource = m_pSourceMap->Begin();
for (;!theErr && ndxSource != m_pSourceMap->End(); ++ndxSource)
{
pSourceInfo = (SourceInfo*)(*ndxSource);
/* Do not call Process source at interrupt time unless
* it is initialized.
*/
if (pSourceInfo->m_pSource &&
(pSourceInfo->m_pSource->IsInitialized() ||
!m_pEngine->AtInterruptTime()))
{
// XXX HP may need to rework
if (!pSourceInfo->m_bDone)
{
theErr = pSourceInfo->m_pSource->ProcessIdle();
if( theErr == HXR_OUTOFMEMORY )
{
goto exitRoutine;
}
}
theErr = SpawnSourceIfNeeded(pSourceInfo);
if( theErr == HXR_OUTOFMEMORY )
{
goto exitRoutine;
}
else
{
theErr = HXR_OK; // filter out HXR_NOTIMPL
}
}
if (pSourceInfo->m_pPeerSourceInfo &&
pSourceInfo->m_pPeerSourceInfo->m_pSource &&
!pSourceInfo->m_pPeerSourceInfo->m_bDone &&
(pSourceInfo->m_pPeerSourceInfo->m_pSource->IsInitialized() ||
!m_pEngine->AtInterruptTime()))
{
theErr = pSourceInfo->m_pPeerSourceInfo->m_pSource->ProcessIdle();
if( theErr == HXR_OUTOFMEMORY )
{
goto exitRoutine;
}
}
}
#if defined(HELIX_FEATURE_PREFETCH)
if (m_pPrefetchManager &&
m_pPrefetchManager->GetNumSources() > 0)
{
m_pPrefetchManager->ProcessIdle();
}
#endif /* HELIX_FEATURE_PREFETCH */
#if defined(HELIX_FEATURE_NEXTGROUPMGR)
if (m_pNextGroupManager->GetNumSources() > 0)
{
m_pNextGroupManager->ProcessIdle();
}
#endif /* HELIX_FEATURE_NEXTGROUPMGR */
// check the status first
if (!m_bContactingDone &&
HXR_OK == GetStatus(unStatusCode, pStatusDesc, unPercentDone))
{
if (HX_STATUS_CONTACTING == unStatusCode && pStatusDesc && m_pAdviseSink)
{
m_pAdviseSink->OnContacting((const char*)pStatusDesc->GetBuffer());
}
else if (HX_STATUS_INITIALIZING != unStatusCode)
{
m_bContactingDone = TRUE;
}
HX_RELEASE(pStatusDesc);
}
// initialize renderes if not done yet..
// this involves reading headers from source object
// creating the right renderers for each stream and pass this
// header to the renderer.
if (!m_bInitialized)
{
/* A temporary hack till we change SMIL fileformat
* to send Layout info in Header
*/
BOOL bIsSmilRenderer = m_bSetupLayoutSiteGroup;
theErr = InitializeRenderers();
#if defined(HELIX_FEATURE_VIDEO)
if (!theErr && m_bInitialized && !m_bPlayerWithoutSources)
{
SetupLayout(/*!m_bSetupLayoutSiteGroup*/ FALSE);
if (bIsSmilRenderer == m_bSetupLayoutSiteGroup &&
m_pSiteSupplier && !m_bBeginChangeLayoutTobeCalled)
{
m_bBeginChangeLayoutTobeCalled = TRUE;
m_pSiteSupplier->DoneChangeLayout();
}
}
#endif /* HELIX_FEATURE_VIDEO */
if (!theErr && m_bInitialized)
{
AdjustPresentationTime();
m_bSetupToBeDone = TRUE;
theErr = SetupAudioPlayer();
}
}
if (m_bPostSetupToBeDone)
{
m_bPostSetupToBeDone = FALSE;
/* Initialize audio services */
if (!theErr && m_bInitialized)
{
m_bIsPresentationClosedToBeSent = TRUE;
if (m_pAdviseSink)
{
m_pAdviseSink->OnPresentationOpened();
}
}
if (!theErr && m_bInitialized)
{
m_ulMinimumAudioPreroll = m_pAudioPlayer->GetInitialPushdown();
SetMinimumPushdown();
}
if (!theErr && m_bInitialized && !m_bIsFirstBegin)
{
CheckSourceRegistration();
ndxSource = m_pSourceMap->Begin();
for (; !theErr && ndxSource != m_pSourceMap->End(); ++ndxSource)
{
SourceInfo* pSourceInfo = (SourceInfo*) (*ndxSource);
HXSource* pSource = pSourceInfo->m_pSource;
if (pSource)
{
theErr = pSource->DoResume();
}
else
{
/* pSource should never be NULL */
HX_ASSERT(FALSE);
}
}
}
/* Start Downloading even if we have not been issued a
* Begin() command
*/
if (!theErr && m_bInitialized && m_bIsFirstBegin && !m_bIsDone)
{
theErr = StartDownload();
}
}
// if it is still not initialized check error code and return
if (theErr || !m_bInitialized)
{
// my first use of goto..!!
goto exitRoutine;
}
/* try to fill up packets from the various source objects for
* different streams so that all of them are upto their preroll
* mark...
*/
UpdateCurrentPlayTime( m_pAudioPlayer->GetCurrentPlayBackTime() );
if (!m_ToBeginRendererList.IsEmpty())
{
CheckBeginList();
}
while (!theErr && !bDone && m_uNumSourcesActive > 0)
{
ndxSource = m_pSourceMap->Begin();
for (;!theErr && ndxSource != m_pSourceMap->End(); ++ndxSource)
{
pSourceInfo = (SourceInfo*)(*ndxSource);
theErr = pSourceInfo->ProcessIdle(bIsFirst, ulNumStreamsToBeFilled,
bIsBuffering, uLowestBuffering);
if (pSourceInfo->m_pPeerSourceInfo)
{
BOOL tmp_bIsFirst = TRUE;
BOOL tmp_bIsBuffering = FALSE;
UINT32 tmp_ulNumStreamsToBeFilled = 0;
UINT16 tmp_uLowestBuffering = 100;
pSourceInfo->m_pPeerSourceInfo->ProcessIdle(tmp_bIsFirst, tmp_ulNumStreamsToBeFilled,
tmp_bIsBuffering, tmp_uLowestBuffering);
}
/* Someone added a source during ProcessIdle.
* Start all over again
*/
if (m_bSourceMapUpdated)
{
break;
}
}
if (bIsBuffering && !m_bIsPlaying)
{
if (!ulLoopEntryTime)
{
ulLoopEntryTime = HX_GET_TICKCOUNT();
}
ndxSource = m_pSourceMap->Begin();
for (;!theErr && ndxSource != m_pSourceMap->End(); ++ndxSource)
{
pSourceInfo = (SourceInfo*)(*ndxSource);
ndxRend = pSourceInfo->m_pRendererMap->Begin();
for (;!theErr && ndxRend != pSourceInfo->m_pRendererMap->End();
++ndxRend)
{
pRendInfo = (RendererInfo*)(*ndxRend);
pRenderer = pRendInfo->m_pRenderer;
if((pRendInfo->m_bInterruptSafe || !m_pEngine->AtInterruptTime())
&& pRenderer)
{
pRenderer->OnBuffering(m_BufferingReason, uLowestBuffering);
}
}
}
m_b100BufferingToBeSent = TRUE;
if (m_pAdviseSink)
{
m_pAdviseSink->OnBuffering(m_BufferingReason, uLowestBuffering);
}
// free some CPU time if we stuck in this WHILE loop too long
if (!theErr &&
CALCULATE_ELAPSED_TICKS(ulLoopEntryTime, HX_GET_TICKCOUNT()) >= MAX_LOOP_EXE_TIME)
{
break;
}
if (!theErr)
{
theErr = ProcessCurrentEvents();
}
}
if (theErr || m_bSourceMapUpdated)
{
m_bSourceMapUpdated = FALSE;
goto exitRoutine;
}
bIsFirst = FALSE;
if (ulNumStreamsToBeFilled == 0)
{
bDone = TRUE;
}
}
// SPECIAL CASE:
// the player received all the packets(m_uNumSourcesActive is 0) and
// EndOfPacket() hasn't been sent to the renderer yet,
// BUT the renderer still calls ReportRebufferStatus()
// we need to make sure the rebuffering is done before calling resume.
if (m_uNumSourcesActive == 0)
{
ndxSource = m_pSourceMap->Begin();
for (;!theErr && ndxSource != m_pSourceMap->End(); ++ndxSource)
{
pSourceInfo = (SourceInfo*)(*ndxSource);
if (!pSourceInfo->IsRebufferDone())
{
bIsBuffering = TRUE;
break;
}
}
}
/* Stop Downloading if we have not been issued a
* Begin() command and we are done with Buffering.
*/
if (!theErr && !bIsBuffering && m_bFastStartInProgress && !m_bIsDone)
{
theErr = PauseDownload();
}
// Process Current Events Due...
if (!theErr)
{
theErr = ProcessCurrentEvents();
}
// repeat source specific
SwitchSourceIfNeeded();
if (!theErr && !bIsBuffering &&
(!m_bResumeOnlyAtSystemTime || !m_pEngine->AtInterruptTime()))
{
theErr = CheckForAudioResume();
}
if (!theErr && !m_bLastGroup && !m_bNextGroupStarted && !m_pEngine->AtInterruptTime())
{
CheckToStartNextGroup();
}
/* Check if live stream has ended */
if (!theErr && m_bInitialized && !m_bPlayerWithoutSources &&
((!m_bIsLive && (!m_ulPresentationDuration ||
(m_ulPresentationDuration < m_ulCurrentPlayTime))) ||
(m_bIsLive && AreAllPacketsSent())) &&
m_uNumSourcesActive == 0)
{
/* If there are any sources that MUST be initialized before playback
* begins/stops, we should not end the presentation here. Instead, wait for
* the stream headers to come down...
*/
if ((m_uNumSourceToBeInitializedBeforeBegin > 0) &&
m_ulPresentationDuration)
{
InternalPause();
}
else if (!m_ulPresentationDuration ||
(m_ulPresentationDuration < m_ulCurrentPlayTime))
{
if (ScheduleOnTimeSync())
{
// schedule a system callback to ensure
// the renderers receive OnTimeSync() on its duration
// AND the clip ends AS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -