📄 srcinfo.cpp
字号:
m_strWallClockName = (const char*)pWallClockName->GetBuffer();
/* We shouldn't already have a wall clock! */
HX_ASSERT(m_pWallClock == NULL);
/*
* Lookup a wall clock with this name, if it's not found then
* we are the first one, and we should create a shared wallclock
* object, add it to the list, and do the standard setup.
*/
void* pLookupResult = NULL;
if (!m_pPlayer->FindSharedWallClocks(m_strWallClockName,pLookupResult))
{
m_pWallClock = new SharedWallClock(m_strWallClockName,
ulStreamStartTime,
m_pPlayer);
}
else
{
m_pWallClock = (SharedWallClock*)pLookupResult;
ulStreamStartTime = m_pWallClock->ResetStartTime(ulStreamStartTime);
}
m_pWallClock->AddUser(this);
}
HX_RELEASE(pValues);
HX_RELEASE(pWallClockName);
return ulStreamStartTime;
}
/*
* -- LIVE SYNC SUPPORT --
*
* Basic clean up support for wall clock object. Notice that after
* calling RemoveUser, you can use the wall clock object since it
* may get deleted... so we always reset our wall clock object
* pointer to NULL.
*/
void
SourceInfo::DoneWithWallClock()
{
if (m_pWallClock)
{
m_pWallClock->RemoveUser(this);
m_pWallClock = NULL;
}
}
HX_RESULT
SourceInfo::ProcessIdle(BOOL bIsFirst,
ULONG32& ulNumStreamsToBeFilled,
BOOL& bIsBuffering,
UINT16& uLowestBuffering,
BOOL bPersistent)
{
HX_RESULT theErr = HXR_OK;
CHXEvent* pEvent = NULL;
HXSource* pSource = NULL;
IHXPendingStatus* pStatus = NULL;
RendererInfo* pRendInfo = NULL;
IHXValues* pHeader = NULL;
HXStream* pStream = NULL;
IHXRenderer* pRenderer = NULL;
STREAM_INFO* pStreamInfo = NULL;
IHXPacket* pPacket = NULL;
UINT16 unStatusCode = 0;
UINT16 unPercentDone = 0;
UINT32 ulPacketTime = 0;
INT64 llActualPacketTime = 0;
INT64 llLastExpectedPacketTime = 0;
IHXBuffer* pStatusDesc = NULL;
BOOL bAtInterrupt = FALSE;
bAtInterrupt = m_pPlayer->m_pEngine->AtInterruptTime();
if (m_bStopped)
{
return HXR_OK;
}
/* Check if a source has not been initialized. This will happen
* ONLY when we start a new track in the mid of a presentation
*/
if (!m_bInitialized)
{
/* Do not initialize source at interrupt time */
if (bAtInterrupt)
{
ScheduleProcessCallback();
return HXR_OK;
}
theErr = InitializeAndSetupRendererSites();
if (theErr || !m_bInitialized)
{
return theErr;
}
}
if (m_bSeekPending)
{
m_bSeekPending = FALSE;
Pause();
Seek(m_ulSeekTime);
m_pSource->DoSeek(m_ulSeekTime);
Begin();
}
pSource = m_pSource;
pStatus = m_pStatus;
// don't start getting events till the player setup has been
// done
if (!m_pPlayer->m_bInitialized ||
m_pPlayer->m_bSetupToBeDone ||
m_pPlayer->m_bPostSetupToBeDone)
{
return HXR_OK;
}
UINT16 uIndex = 0;
BOOL bHandled = TRUE;
llLastExpectedPacketTime = m_pSource->GetLastExpectedPacketTime();
LISTPOSITION posRend = m_pCurrentScheduleList->GetHeadPosition();
for (; uIndex < m_pCurrentScheduleList->GetCount(); uIndex++)
{
BOOL bSentMe = TRUE;
BOOL bEndMe = FALSE;
llActualPacketTime = 0;
theErr = HXR_OK;
if (uIndex > 0)
{
if (bHandled)
{
posRend = m_pCurrentScheduleList->RemoveAt(posRend);
LISTPOSITION listRet = m_pCurrentScheduleList->AddTail(pRendInfo);
// This check is critical for catching oom errors. XXXJHHB
if( listRet == NULL )
{
return HXR_OUTOFMEMORY;
}
}
else
{
m_pCurrentScheduleList->GetNext(posRend);
}
}
bHandled = TRUE;
pRendInfo = (RendererInfo*)
m_pCurrentScheduleList->GetAt(posRend);
pStreamInfo = pRendInfo->m_pStreamInfo;
if (pStreamInfo->m_bSrcInfoStreamDone)
{
// SPECIAL CASE:
// the player received all the packets(m_bSrcStreamDone is TRUE) and
// EndOfPacket() hasn't been sent to the renderer yet,
// BUT the renderer still calls ReportRebufferStatus()
if (!IsRebufferDone())
{
bIsBuffering = TRUE;
}
else
{
CheckIfDone();
}
continue;
}
if (bIsFirst)
{
pStreamInfo->m_bSrcInfoStreamFillingDone = FALSE;
ulNumStreamsToBeFilled++;
}
BOOL bThisSourceBuffering = FALSE;
if (!bPersistent)
{
// every HXSource has to implement IID_IHXPendingStatus
HX_ASSERT(pStatus);
HX_VERIFY(HXR_OK == pStatus->GetStatus(unStatusCode, pStatusDesc,
unPercentDone));
HX_RELEASE(pStatusDesc);
if ((HX_STATUS_BUFFERING == unStatusCode && unPercentDone < 100) ||
HX_STATUS_CONTACTING == unStatusCode)
{
bIsBuffering = TRUE;
bThisSourceBuffering = TRUE;
if (uLowestBuffering > unPercentDone)
{
uLowestBuffering = unPercentDone;
}
}
}
/* the event times are actual ts - preroll.. so we do not
* need to add preroll in calculations here...
*/
UINT32 ulDeliveryTime = m_pPlayer->m_ulCurrentPlayTime +
m_pPlayer->m_ulLowestGranularity;
#ifdef _MACINTOSH
#define ADDITIONAL_PREDELIVERY_TIME 4000
/* on Mac we try to be even farther ahead than the timeline in
* packet delivery since the callbacks are not that smooth
* and if we are really close to the wire, it results in
* unnecccessary re-buffers.
*/
ulDeliveryTime += ADDITIONAL_PREDELIVERY_TIME;
#endif
if (pSource)
{
pSource->FillRecordControl();
}
if (bPersistent || bThisSourceBuffering ||
(pRendInfo->m_ulLatestEventTime <= ulDeliveryTime))
{
theErr = pSource->GetEvent(pStreamInfo->m_uStreamNumber, pEvent);
if (!theErr)
{
pPacket = pEvent->GetPacket();
if (pEvent->IsPreSeekEvent())
{
// associate the packet with its renderer..
pEvent->m_pRendererInfo = pRendInfo;
if (!bAtInterrupt || pRendInfo->m_bInterruptSafe)
{
theErr = m_pPlayer->SendPacket(pEvent);
delete pEvent;
}
else
{
// insert event in the common packet/event list...
theErr = m_pPlayer->m_EventList.InsertEvent(pEvent);
if( theErr == HXR_OUTOFMEMORY )
{
return HXR_OUTOFMEMORY;
}
pRendInfo->m_ulNumberOfPacketsQueued++;
}
continue;
}
if (!pPacket->IsLost())
{
ulPacketTime = pPacket->GetTime();
llActualPacketTime =
pRendInfo->m_pStreamInfo->BufferingState().CreateINT64Timestamp(ulPacketTime);
if (m_llLatestPacketTime < llActualPacketTime)
{
m_llLatestPacketTime = llActualPacketTime;
}
pRendInfo->m_ulLatestEventTime = pEvent->GetTimeStartPos();
if (pSource->IsLive() && pRendInfo->m_bIsFirstPacket)
{
pRendInfo->m_bIsFirstPacket = FALSE;
/*
* -- LIVE SYNC SUPPORT --
*
* We used to just set the stream start time to the
* timestamp of this first packet. Now we use this
* helper function to implement support for sharing
* start times for sources off of the same wall clock.
* See other LIVE SYNC SUPPORT comments for more
* details.
*/
UINT32 ulLiveStart = CalculateLiveStartTime(pPacket);
pRendInfo->m_ulStreamStartTime = ulLiveStart;
m_ulStreamStartTime = ulLiveStart;
UINT32 ulLowestTime = 0;
BOOL bAtLeastOneLowestTime = FALSE;
UINT16 uNumLowestKnown = 0;
CHXMapLongToObj::Iterator tmpndxRend = m_pRendererMap->Begin();
for (;!theErr && tmpndxRend != m_pRendererMap->End();
++tmpndxRend)
{
RendererInfo* pTmpRendInfo = (RendererInfo*)(*tmpndxRend);
/* Have we received the lowest packet?*/
if (!pTmpRendInfo->m_bIsFirstPacket)
{
uNumLowestKnown++;
if (!bAtLeastOneLowestTime)
{
bAtLeastOneLowestTime = TRUE;
ulLowestTime = pTmpRendInfo->m_ulStreamStartTime;
SetLiveSyncStartTime(pSource, pTmpRendInfo, ulLowestTime);
}
else
{
if (ulLowestTime > pTmpRendInfo->m_ulStreamStartTime)
{
ulLowestTime = pTmpRendInfo->m_ulStreamStartTime;
}
}
}
}
if (uNumLowestKnown > 1)
{
tmpndxRend = m_pRendererMap->Begin();
for (;!theErr && tmpndxRend != m_pRendererMap->End();
++tmpndxRend)
{
RendererInfo* pTmpRendInfo = (RendererInfo*)(*tmpndxRend);
/* Have we received the lowest packet?*/
if (!pTmpRendInfo->m_bIsFirstPacket)
{
pTmpRendInfo->m_ulStreamStartTime = ulLowestTime;
SetLiveSyncStartTime(pSource, pTmpRendInfo, ulLowestTime);
}
}
}
}
if ((!pSource->IsLive() || pSource->isRestrictedLiveStream()) &&
llActualPacketTime > llLastExpectedPacketTime)
{
// XXX HP
// work around since the rule flag of all RTSP packets are set to
// HX_ASM_SWITCH_ON only and this could cause the stream doesn't end
// properly if its endtime was changed after the first resume has been
// sent
// THIS WILL BE FIXED IN THE NEXT SERVER RELEASE("dial-tone")
if (pSource->m_bRTSPRuleFlagWorkAround)
{
bSentMe = FALSE;
bEndMe = TRUE;
}
else
{
pRendInfo->m_pStream->PostEndTimePacket(pPacket, bSentMe, bEndMe);
}
}
}
if (bSentMe)
{
// clear up the post events which were not sent
if (pStreamInfo->m_pPostEndTimeEventList)
{
while (pStreamInfo->m_pPostEndTimeEventList->GetNumEvents())
{
CHXEvent* pPostEndTimeEvent = pStreamInfo->m_pPostEndTimeEventList->RemoveHead();
// associate the packet with its renderer..
pPostEndTimeEvent->m_pRendererInfo = pRendInfo;
// insert event in the common packet/event list...
theErr = m_pPlayer->m_EventList.InsertEvent(pPostEndTimeEvent);
if( theErr == HXR_OUTOFMEMORY )
{
return HXR_OUTOFMEMORY;
}
pRendInfo->m_ulNumberOfPacketsQueued++;
}
}
// associate the packet with its renderer..
pEvent->m_pRendererInfo = pRendInfo;
// insert event in the common packet/event list...
theErr = m_pPlayer->m_EventList.InsertEvent(pEvent);
if( theErr == HXR_OUTOFMEMORY )
{
return HXR_OUTOFMEMORY;
}
pRendInfo->m_ulNumberOfPacketsQueued++;
}
else
{
if (!pStreamInfo->m_pPostEndTimeEventList)
{
pStreamInfo->m_pPostEndTimeEventList = new CHXEventList();
}
if (pStreamInfo->m_pPostEndTimeEventList)
{
//{FILE* f1 = ::fopen("c:\\temp\\out.txt", "a+"); ::fprintf(f1, "bSentMe is FALSE PacketTime: %lu PacketRule: %u\n", pEvent->GetPacket()->GetTime(), pEvent->GetPacket()->GetASMRuleNumber());::fclose(f1);}
theErr = pStreamInfo->m_pPostEndTimeEventList->InsertEvent(pEvent);
if( theErr == HXR_OUTOFMEMORY )
{
return theErr;
}
}
}
}
else
{
bHandled = FALSE;
}
if (theErr && !bPersistent)
{
if (!pStreamInfo->m_bSrcInfoStreamFillingDone &&
ulNumStreamsToBeFilled > 0)
{
pStreamInfo->m_bSrcInfoStreamFillingDone = TRUE;
ulNumStreamsToBeFilled--;
}
}
}
else
{
if (!pStreamInfo->m_bSrcInfoStreamFillingDone &&
ulNumStreamsToBeFilled > 0)
{
pStreamInfo->m_bSrcInfoStreamFillingDone = TRUE;
ulNumStreamsToBeFilled--;
}
}
if (theErr == HXR_BUFFERING)
{
if (bPersistent)
{
bIsBuffering = TRUE;
}
}
else if (theErr == HXR_AT_END)
{
if (!pStreamInfo->m_bSrcInfoStreamDone)
{
if (!bAtInterrupt || pRendInfo->m_bInterruptSafe)
{
pStreamInfo->m_bSrcInfoStreamDone = TRUE;
pStreamInfo->ResetPostEndTimeEventList();
if (pRendInfo->m_ulNumberOfPacketsQueued == 0 &&
pRendInfo->m_pRenderer)
{
m_pPlayer->SendPostSeekIfNecessary(pRendInfo);
pRendInfo->m_pRenderer->OnEndofPackets();
pRendInfo->m_bOnEndOfPacketSent = TRUE;
}
CheckIfDone();
}
else
{
ScheduleProcessCallback();
continue;
}
}
}
else if (theErr == HXR_NO_DATA)
{
/* mask this error */
theErr = HXR_OK;
}
if (!llActualPacketTime)
{
STREAM_INFO* pStrInfo = pRendInfo->m_pStreamInfo;
UINT32 ulPktTime =
pStrInfo->BufferingState().LastPacketTimestamp();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -