📄 srcinfo.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 "hxtypes.h"
#include "hxcom.h"
#include "hxresult.h"
#include "smiltype.h"
#include "hxcomm.h" // IHXRegistryID
#include "hxengin.h"
#include "hxcore.h"
#include "hxupgrd.h"
#include "hxrendr.h"
#include "hxasm.h"
#include "hxsmbw.h"
#include "hxgroup.h"
#include "hxausvc.h"
#include "hxslist.h"
#include "hxmap.h"
#include "chxpckts.h"
#include "chxeven.h"
#include "chxelst.h"
#include "strminfo.h"
#include "timeval.h"
#include "hxbsrc.h"
#include "hxsrc.h"
#include "hxstrm.h"
#include "hxsmstr.h"
#include "hxaudply.h"
#include "basgroup.h"
#include "advgroup.h"
#include "hxthread.h"
#include "hxtick.h"
#include "hxstrutl.h"
#include "srcinfo.h"
#include "hxplay.h"
#include "hxcleng.h"
#include "plghand2.h"
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
#define TIME_SYNC_FUDGE_FACTOR 10
#define GOTOEXITONERROR(theErr, label) if ((theErr) != 0) goto label
SourceInfo::SourceInfo(HXPlayer* pPlayer)
{
m_pRendererMap = new CHXMapLongToObj;
m_pPlayer = pPlayer;
m_pPlayer->AddRef();
m_pSource = NULL;
m_bDone = FALSE;
m_bStopped = FALSE;
m_bInitialized = FALSE;
m_pStatus = NULL;
m_bAllPacketsReceived = FALSE;
m_bActive = TRUE;
m_bIsPersistentSource = FALSE;
m_bIsRegisterSourceDone = FALSE;
m_uTrackID = 0;
m_uGroupID = 0;
m_bToBeResumed = TRUE;
m_bAreStreamsSetup = FALSE;
m_bTrackStartedToBeSent = TRUE;
m_bTrackStoppedToBeSent = TRUE;
m_bPrefetch = FALSE;
m_bLoadPluginAttempted = FALSE;
m_pCurrentScheduleList = NULL;
m_ulSourceDuration = 0;
m_ulMaxDuration = 0;
m_ulTrackDuration = 0;
m_ulTotalTrackDuration = 0;
m_pDependNode = NULL;
m_uNumDependencies = 0;
m_bTobeInitializedBeforeBegin = FALSE;
m_bAltURL = FALSE;
m_lastErrorFromMainURL = HXR_OK;
m_lastError = HXR_OK;
m_bLocked = FALSE;
m_bIsTrackDurationSet = FALSE;
m_bDurationTimeSyncScheduled = FALSE;
m_bAudioDeviceReflushHint = FALSE;
m_pProcessCallback = new CHXGenericCallback((void*)this, (fGenericCBFunc)ProcessCallback);
m_pProcessCallback->AddRef();
m_prefetchType = PrefetchUnknown;
m_ulPrefetchValue = 0;
m_uSoundLevel = 100;
m_fillType = FillRemove;
m_pPeerSourceInfo = NULL;
m_bSeekPending = FALSE;
m_bIndefiniteDuration = FALSE;
m_bRepeatIndefinite = FALSE;
m_bSeekToLastFrame = FALSE;
m_ulRepeatInterval = 0;
m_ulRepeatDelayTimeOffset = 0;
m_ulSeekTime = 0;
m_ulPausedStartTime = 0;
m_bLeadingSource = TRUE;
m_bRepeatPending = FALSE;
m_pRepeatList = NULL;
m_curPosition = 0;
m_ulPersistentComponentID = MAX_UINT32;
m_ulPersistentComponentSelfID = MAX_UINT32;
m_pRendererAdviseSink = NULL;
#ifdef THREADS_SUPPORTED
HXMutex::MakeMutex(m_pMutex);
#else
HXMutex::MakeStubMutex(m_pMutex);
#endif
/*
* The following members are needed for live sync support.
*/
m_pWallClock = NULL;
m_ulStreamStartTime = 0;
m_llLatestPacketTime = 0;
}
SourceInfo::~SourceInfo()
{
if (m_pProcessCallback && m_pPlayer->m_pScheduler)
{
m_pPlayer->m_pScheduler->Remove(m_pProcessCallback->GetPendingCallback());
m_pProcessCallback->CallbackCanceled();
}
if (m_pRepeatList)
{
while (m_pRepeatList->GetCount())
{
RepeatInfo* pRepeatInfo = (RepeatInfo*)m_pRepeatList->RemoveHead();
HX_DELETE(pRepeatInfo);
}
HX_DELETE(m_pRepeatList);
}
HX_RELEASE(m_pStatus);
HX_RELEASE(m_pProcessCallback);
HX_RELEASE(m_pPlayer);
HX_DELETE(m_pCurrentScheduleList);
HX_VECTOR_DELETE(m_pDependNode);
HX_DELETE(m_pMutex);
HX_DELETE(m_pRendererMap);
/*
* For live sync support, we may have used a shared wall
* clock, if so then we're done with it now, so we may need
* to do some cleanup work here.
*/
DoneWithWallClock();
};
HX_RESULT
SourceInfo::Begin()
{
HX_RESULT theErr = HXR_OK;
if(!m_pSource || !m_pSource->IsInitialized())
{
return HXR_OK;
}
if (m_pPlayer->m_bInitialized)
{
// handle the seek so that the server will be notified
// via the play request upon the first resume
if (m_bSeekPending)
{
m_bSeekPending = FALSE;
Pause();
Seek(m_ulSeekTime);
m_pSource->DoSeek(m_ulSeekTime);
}
theErr = m_pSource->DoResume();
}
if (!m_bInitialized)
{
return HXR_OK;
}
/* Only send this OnBegin()'s if not the first begin. In the case
* of the first begin, these are actually sent after the header's
* arrive...
*/
if (!m_pPlayer->m_bIsFirstBegin && !m_pPlayer->m_bInternalPauseResume)
{
CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
for (; !theErr &&
ndxRend != m_pRendererMap->End(); ++ndxRend)
{
RendererInfo* pRendInfo = (RendererInfo*) (*ndxRend);
if (!pRendInfo->m_bInitialBeginToBeSent)
{
IHXRenderer* pRend = (IHXRenderer*) pRendInfo->m_pRenderer;
pRend->OnBegin(m_pPlayer->m_ulCurrentPlayTime);
}
}
}
return theErr;
}
HX_RESULT
SourceInfo::Pause()
{
HX_RESULT theErr = HXR_OK;
if(!m_pSource)
{
return HXR_OK;
}
theErr = m_pSource->DoPause();
/* Do not send OnPause to renderers if it is an internal Pause */
if (m_pPlayer->m_bInternalPauseResume || !m_bInitialized)
{
return theErr;
}
CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
for (; !theErr &&
ndxRend != m_pRendererMap->End(); ++ndxRend)
{
RendererInfo* pRendInfo = (RendererInfo*) (*ndxRend);
IHXRenderer* pRend = (IHXRenderer*) pRendInfo->m_pRenderer;
m_pPlayer->m_pScheduler->Remove(
pRendInfo->m_pTimeSyncCallback->GetPendingCallback());
pRendInfo->m_pTimeSyncCallback->CallbackCanceled();
pRendInfo->m_bIsFirstCallback = TRUE;
pRend->OnPause(m_pPlayer->m_ulCurrentPlayTime);
}
return theErr;
}
HX_RESULT
SourceInfo::Seek(UINT32 ulSeekTo)
{
HX_RESULT rc = HXR_OK;
INT64 llLastExpectedPacketTime = 0;
BOOL bSeekToLastFrame = FALSE;
BOOL bDurationTimeSyncSent = TRUE;
UINT32 ulValue = 0;
RendererInfo* pRendInfo = NULL;
STREAM_INFO* pStreamInfo = NULL;
IHXValues* pStatus = NULL;
IHXPersistentRenderer* pPersRender = NULL;
IHXPersistentComponent* pPersComp = NULL;
HXPersistentComponentManager* pPersCompMgr = NULL;
CHXMapLongToObj::Iterator ndx;
/* m_pSource should never be NULL */
HX_ASSERT(m_pSource);
if(!m_pSource || !m_bInitialized)
{
return HXR_OK;
}
m_bDone = FALSE;
m_bActive = TRUE;
m_bAllPacketsReceived = FALSE;
llLastExpectedPacketTime = m_pSource->GetLastExpectedPacketTime();
/* Are we seeking past the last expected packet time?
* If so, verify the "show" attribute to see whether we need to
* get the last video frame
*/
if (!m_pSource->IsLive() && ulSeekTo >= INT64_TO_UINT32(llLastExpectedPacketTime + m_pSource->GetDelay()))
{
#if defined(HELIX_FEATURE_NESTEDMETA)
pPersCompMgr = m_pPlayer->m_pPersistentComponentManager;
if (FillFreeze == m_fillType && pPersCompMgr)
{
rc = pPersCompMgr->GetPersistentComponent(m_ulPersistentComponentID,
pPersComp);
HX_ASSERT(HXR_OK == rc);
if (pPersComp)
{
rc = pPersComp->GetPersistentRenderer(pPersRender);
HX_ASSERT(HXR_OK == rc);
rc = pPersRender->GetElementStatus(m_uGroupID,
m_uTrackID,
ulSeekTo,
pStatus);
HX_ASSERT(HXR_OK == rc);
if (pStatus && HXR_OK == pStatus->GetPropertyULONG32("Show", ulValue))
{
bSeekToLastFrame = (BOOL)ulValue;
}
HX_RELEASE(pStatus);
HX_RELEASE(pPersRender);
HX_RELEASE(pPersComp);
}
}
else if (FillHold == m_fillType)
{
bSeekToLastFrame = TRUE;
}
#else
if (FillHold == m_fillType)
{
bSeekToLastFrame = TRUE;
}
#endif /* HELIX_FEATURE_NESTEDMETA */
}
// also check if we already sent OnTimeSync() upon its duration ends
// which means the renderer got the last frame so we don't need to issue
// last frame seek
if (bSeekToLastFrame)
{
ndx = m_pRendererMap->Begin();
for (; ndx != m_pRendererMap->End(); ++ndx)
{
pRendInfo = (RendererInfo*)(*ndx);
if (!pRendInfo->m_bDurationTimeSyncSent)
{
bDurationTimeSyncSent = FALSE;
}
}
if (bDurationTimeSyncSent)
{
bSeekToLastFrame = FALSE;
}
}
CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
for (; ndxRend != m_pRendererMap->End(); ++ndxRend)
{
RendererInfo* pRendInfo = (RendererInfo*)(*ndxRend);
IHXRenderer* pRend = (IHXRenderer*)pRendInfo->m_pRenderer;
STREAM_INFO* pStreamInfo = pRendInfo->m_pStreamInfo;
pStreamInfo->m_bSrcInfoStreamDone = FALSE;
pRendInfo->m_pStream->ResetASMRuleState();
pStreamInfo->ResetPostEndTimeEventList();
if (m_pSource->IsLive())
{
#if defined(HELIX_FEATURE_RECORDCONTROL)
if(m_pSource->IsPlayingFromRecordControl())
{
pStreamInfo->m_ulTimeBeforeSeek = m_pPlayer->m_ulTimeBeforeSeek;
pStreamInfo->m_ulTimeAfterSeek = m_pPlayer->m_ulTimeAfterSeek;
if (pRendInfo->m_bTimeDiffPositive)
{
pStreamInfo->m_ulTimeBeforeSeek += pRendInfo->m_ulTimeDiff;
pStreamInfo->m_ulTimeAfterSeek += pRendInfo->m_ulTimeDiff;
}
else
{
pStreamInfo->m_ulTimeBeforeSeek -= pRendInfo->m_ulTimeDiff;
pStreamInfo->m_ulTimeAfterSeek -= pRendInfo->m_ulTimeDiff;
}
}
else
#endif /* HELIX_FEATURE_RECORDCONTROL */
{
UINT32 ulLastTimeSync = (LONG32) m_pPlayer->m_ulLiveSeekTime;
if (pRendInfo->m_bTimeDiffPositive)
{
ulLastTimeSync += pRendInfo->m_ulTimeDiff;
}
else
{
ulLastTimeSync -= pRendInfo->m_ulTimeDiff;
}
pStreamInfo->m_ulTimeBeforeSeek = ulLastTimeSync;
pStreamInfo->m_ulTimeAfterSeek = ulLastTimeSync + m_pPlayer->m_ulElapsedPauseTime;
}
}
else
{
pStreamInfo->m_ulTimeBeforeSeek = m_pPlayer->m_ulTimeBeforeSeek;
if (bSeekToLastFrame)
{
HX_ASSERT(llLastExpectedPacketTime + m_pSource->GetDelay() >= 1);
pStreamInfo->m_ulTimeAfterSeek = INT64_TO_UINT32(llLastExpectedPacketTime + m_pSource->GetDelay() - 1);
}
else
{
pStreamInfo->m_ulTimeAfterSeek = m_pPlayer->m_ulTimeAfterSeek;
}
}
pRend->OnPreSeek(pStreamInfo->m_ulTimeBeforeSeek,
pStreamInfo->m_ulTimeAfterSeek);
pStreamInfo->m_pStream->m_bPostSeekToBeSent = TRUE;
// reset renderer info attributes
pRendInfo->m_ulLatestEventTime = 0;
pRendInfo->m_bIsFirstCallback = TRUE;
pRendInfo->m_ulLastSyncTime = 0;
pRendInfo->m_ulNextDueSyncTime = m_pPlayer->m_ulCurrentPlayTime;
/* Do we need to send a time sync for renderer duration? */
if (bSeekToLastFrame || pRendInfo->m_ulNextDueSyncTime <= pRendInfo->m_ulDuration)
{
pRendInfo->m_bDurationTimeSyncSent = FALSE;
pRendInfo->m_bOnEndOfPacketSent = FALSE;
}
else
{
pRendInfo->m_bDurationTimeSyncSent = TRUE;
}
m_pPlayer->m_pScheduler->Remove(
pRendInfo->m_pTimeSyncCallback->GetPendingCallback());
pRendInfo->m_pTimeSyncCallback->CallbackCanceled();
if (!pRendInfo->m_bInitialBeginToBeSent)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -