📄 srcinfo.cpp
字号:
pRendInfo->m_bInitialBeginToBeSent = TRUE;
m_pPlayer->EnterToBeginList(pRendInfo);
}
if (m_pSource->IsLive())
{
pRendInfo->m_BufferingReason = BUFFERING_LIVE_PAUSE;
}
else
{
pRendInfo->m_BufferingReason = BUFFERING_SEEK;
}
}
m_bSeekToLastFrame = bSeekToLastFrame;
m_llLatestPacketTime = 0;
return HXR_OK;
}
HX_RESULT
SourceInfo::BeginTrack(void)
{
#if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
HX_RESULT rc = HXR_OK;
UINT32 ulDelay = 0;
UINT32 ulPausedTime = 0;
RendererInfo* pRendInfo = NULL;
STREAM_INFO* pStreamInfo = NULL;
CHXAudioPlayer* pAudioPlayer = NULL;
CHXMapLongToObj::Iterator ndxRend;
if (!m_pSource)
{
rc = HXR_UNEXPECTED;
goto cleanup;
}
if (m_pSource->IsPaused())
{
ulPausedTime = m_pPlayer->m_ulCurrentPlayTime - m_ulPausedStartTime;
ulDelay = m_pSource->GetDelay() + ulPausedTime;
// update source's delay time which will call sourceinfo's
// UpdateDelay()
m_pSource->UpdateDelay(ulDelay);
// resume
m_pSource->ResumeAudioStreams();
rc = Begin();
}
// track is stopped ahead of its duration
else if (m_bStopped)
{
m_bStopped = FALSE;
m_bSeekPending = TRUE;
m_ulSeekTime = m_pPlayer->m_ulCurrentPlayTime;
m_pSource->ReSetup();
}
// either track has not been played yet
// or track is still playing
else
{
rc = HXR_FAILED;
goto cleanup;
}
cleanup:
return rc;
#else
return HXR_NOTIMPL;
#endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
}
HX_RESULT
SourceInfo::PauseTrack(void)
{
#if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
HX_RESULT rc = HXR_OK;
// stop the source
if (m_pSource)
{
m_pSource->PauseAudioStreams();
}
m_ulPausedStartTime = m_pPlayer->m_ulCurrentPlayTime;
rc = Pause();
return rc;
#else
return HXR_NOTIMPL;
#endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
}
HX_RESULT
SourceInfo::SeekTrack(UINT32 ulSeekTime)
{
// low priority since it is rarely used by the SMIL
return HXR_NOTIMPL;
}
HX_RESULT
SourceInfo::StopTrack(void)
{
#if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
HX_RESULT rc = HXR_OK;
m_bStopped = TRUE;
// stop the source
if (m_pSource)
{
m_pSource->RemoveAudioStreams();
}
Reset();
m_bDone = TRUE;
m_pPlayer->m_uNumSourcesActive--;
return rc;
#else
return HXR_NOTIMPL;
#endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
}
HX_RESULT
SourceInfo::SetSoundLevel(UINT16 uSoundLevel, BOOL bReflushAudioDevice)
{
m_uSoundLevel = uSoundLevel;
m_pSource->SetSoundLevel(uSoundLevel, bReflushAudioDevice);
return HXR_OK;
}
void
SourceInfo::Reset()
{
/* m_pSource should never be NULL */
HX_ASSERT(m_pSource);
if (!m_pSource)
{
return;
}
#if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
if(m_bIsPersistentSource)
{
m_bDone = FALSE;
m_bAllPacketsReceived = 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;
/* Reset the latest packet time */
pRendInfo->m_ulLatestEventTime = 0;
m_pPlayer->m_pScheduler->Remove(
pRendInfo->m_pTimeSyncCallback->GetPendingCallback());
pRendInfo->m_pTimeSyncCallback->CallbackCanceled();
pRendInfo->m_bIsFirstCallback = TRUE;
pRendInfo->m_ulLastSyncTime = 0;
pRendInfo->m_ulNumberOfPacketsQueued= 0;
pRendInfo->m_ulNextDueSyncTime = 0;
if (!pRendInfo->m_bInitialBeginToBeSent && pRendInfo->m_pRenderer)
{
pRendInfo->m_bInitialBeginToBeSent = TRUE;
m_pPlayer->EnterToBeginList(pRendInfo);
}
}
}
else
#endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
{
DoCleanup();
RenderersCleanup();
}
return;
}
void
SourceInfo::DoCleanup(EndCode endCode)
{
if (m_pProcessCallback && m_pPlayer->m_pScheduler)
{
m_pPlayer->m_pScheduler->Remove(m_pProcessCallback->GetPendingCallback());
m_pProcessCallback->CallbackCanceled();
}
if (m_bIsPersistentSource)
{
return;
}
m_bLocked = TRUE;
m_pMutex->Lock();
CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
for (; ndxRend != m_pRendererMap->End(); ++ndxRend)
{
RendererInfo* pRendInfo = (RendererInfo*)(*ndxRend);
/* Tell each renderer that we are done with the stream */
if(pRendInfo)
{
if (pRendInfo->m_pStream &&
pRendInfo->m_pStreamInfo && pRendInfo->m_pStreamInfo->m_pHeader)
{
IHXBuffer* pMimeTypeBuffer = NULL;
pRendInfo->m_pStreamInfo->m_pHeader->GetPropertyCString("MimeType", pMimeTypeBuffer);
if (pMimeTypeBuffer && pMimeTypeBuffer->GetBuffer() &&
::strcasecmp((const char*) pMimeTypeBuffer->GetBuffer(), "application/vnd.rn-objectsstream") == 0 ||
::strcasecmp((const char*) pMimeTypeBuffer->GetBuffer(), "application/x-rn-objects") == 0 ||
::strcasecmp((const char*) pMimeTypeBuffer->GetBuffer(), "application/vnd.rn-objects") == 0)
{
m_pPlayer->m_pEngine->m_lROBActive--;
HX_ASSERT(m_pPlayer->m_pEngine->m_lROBActive >=0 );
}
HX_RELEASE(pMimeTypeBuffer);
}
if(pRendInfo->m_pRenderer)
pRendInfo->m_pRenderer->EndStream();
if (pRendInfo->m_bInitialBeginToBeSent)
{
m_pPlayer->RemoveFromPendingList(pRendInfo);
}
if (pRendInfo->m_pTimeSyncCallback)
{
//{FILE* f1 = ::fopen("c:\\temp\\ts.txt", "a+"); ::fprintf(f1, "%p RELEASING TimeSyncCallback: Pending: %d Handle: %lu\n", pRendInfo->m_pTimeSyncCallback, (int)pRendInfo->m_bIsCallbackPending, (UINT32) pRendInfo->m_PendingHandle);::fclose(f1);}
m_pPlayer->m_pScheduler->Remove(
pRendInfo->m_pTimeSyncCallback->GetPendingCallback());
pRendInfo->m_pTimeSyncCallback->CallbackCanceled();
HX_RELEASE(pRendInfo->m_pTimeSyncCallback);
}
HX_RELEASE(pRendInfo->m_pStream);
}
}
// cleanup (i.e. registry)
m_pSource->DoCleanup(endCode);
UnRegister();
m_lastError = HXR_OK;
m_bAreStreamsSetup = FALSE;
m_bDone = FALSE;
m_bInitialized = FALSE;
m_bSeekPending = FALSE;
m_bSeekToLastFrame = FALSE;
m_pMutex->Unlock();
m_bLocked = FALSE;
}
void
SourceInfo::Stop(EndCode endCode)
{
/* We have already been here once */
if (m_pSource == NULL)
{
return;
}
DoCleanup(endCode);
if (m_bIsPersistentSource)
{
return;
}
m_bLocked = TRUE;
m_pMutex->Lock();
m_pSource->Stop();
#if defined(HELIX_FEATURE_BASICGROUPMGR)
if (m_bTrackStoppedToBeSent)
{
m_pPlayer->m_pGroupManager->TrackStopped(m_uGroupID, m_uTrackID);
m_bTrackStoppedToBeSent = FALSE;
if (m_pPeerSourceInfo)
{
m_pPeerSourceInfo->m_bTrackStoppedToBeSent = FALSE;
}
}
#endif /* HELIX_FEATURE_BASICGROUPMGR */
m_pMutex->Unlock();
m_bLocked = FALSE;
}
void
SourceInfo::Remove()
{
// stop the source
if (m_pSource)
{
m_pSource->RemoveAudioStreams();
}
m_bDone = TRUE;
Stop();
CloseRenderers();
}
/*
* -- LIVE SYNC SUPPORT --
*
* SharedWallClock class is used for live sync support.
* There is one of these objects per shared wall clock.
*
* This object will also be associated with an HXPlayer
* since we won't ever share wall clocks between two players.
* This is an intentional design choice, since it doesn't
* reall make sense to do any sync-ing across multiple players.
*
* This object will keep a list of source's that are sharing
* it. This is mainly needed so that the wall clock can
* reset the start time for all the sources in the event that
* it gets a new start time that is earlier than it had
* previously thought. Basically, the start time of the wall
* clock is what does the syncing.
*/
SharedWallClock::SharedWallClock
(
const char* pName,
UINT32 ulStartTime,
HXPlayer* pPlayer
)
: m_ulStartTime(ulStartTime)
, m_strName(pName)
, m_pPlayer(pPlayer)
{
HX_ASSERT(m_pPlayer);
(*m_pPlayer->m_pSharedWallClocks)[pName] = this;
};
/*
* -- LIVE SYNC SUPPORT --
*
* Obviously this is the method that handles resyncing the
* start times for all the sources that share the wall clock.
*
* This method also returns the start time. The intended useage
* is for the caller to pass the start time that it expects, and
* then respect the start time that is returned. In the event that
* the input start time is less than the previously known start
* time, then all sources are reset.
*/
UINT32
SharedWallClock::ResetStartTime(UINT32 ulStartTime)
{
if (ulStartTime < m_ulStartTime)
{
m_ulStartTime = ulStartTime;
CHXSimpleList::Iterator indx = m_UserList.Begin();
for (; indx != m_UserList.End(); ++indx)
{
SourceInfo* pSourceInfo = (SourceInfo*)(*indx);
pSourceInfo->ResetStartTime(ulStartTime);
}
}
return m_ulStartTime;
};
/*
* -- LIVE SYNC SUPPORT --
*
* Nothing tricky here, we just track the incoming user on our
* list of known users.
*/
void
SharedWallClock::AddUser(SourceInfo* pSourceInfo)
{
m_UserList.AddTail(pSourceInfo);
};
/*
* -- LIVE SYNC SUPPORT --
*
* This method removes users from the shared clock's user list
* and also cleans up the shared clock when the last user is
* removed. So, any caller of this method should take note to
* NOT use the shared clock after calling this method.
*/
void
SharedWallClock::RemoveUser(SourceInfo* pSourceInfo)
{
LISTPOSITION pos = m_UserList.Find(pSourceInfo);
HX_ASSERT(pos);
m_UserList.RemoveAt(pos);
if (m_UserList.IsEmpty())
{
m_pPlayer->m_pSharedWallClocks->RemoveKey(m_strName);
delete this;
}
};
/*
* -- LIVE SYNC SUPPORT --
*
* If the start time is changed for a source then all the
* renderer's need to have their start time's reset. This
* method just loops through the renderer info to do the work.
*/
void
SourceInfo::ResetStartTime(UINT32 ulStartTime)
{
if (ulStartTime < m_ulStreamStartTime)
{
m_ulStreamStartTime = ulStartTime;
CHXMapLongToObj::Iterator indx = m_pRendererMap->Begin();
for (; indx != m_pRendererMap->End(); ++indx)
{
RendererInfo* pRendererInfo = (RendererInfo*)(*indx);
pRendererInfo->m_ulStreamStartTime = ulStartTime;
}
}
};
/*
* -- LIVE SYNC SUPPORT --
*
* This is the real work horse for live sync support. This
* method actually determines if the URL for the source is
* targeted at a shared wall clock by looking for the wallclock
* option in the URL.
*
* If the wallclock name is found then we try to find the wall
* clock object for this name and player. If we don't find it
* then we create a new clock. If we do find it then we want
* to determine if the start time should be reset to the lower
* value. We also return the start time to be stored in the
* renderers.
*/
UINT32
SourceInfo::CalculateLiveStartTime(IHXPacket* pFirstPacket)
{
UINT32 ulStreamStartTime = pFirstPacket->GetTime();;
/*
* Find out if this live feed has a "wallclock" property.
*/
CHXURL* pURL = m_pSource->GetCHXURL();
IHXValues* pValues = pURL->GetOptions();
IHXBuffer* pWallClockName = NULL;
pValues->GetPropertyBuffer("wallclock", pWallClockName);
if (pWallClockName)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -