📄 hxflsrc.cpp
字号:
}
seekTime += m_ulStartTime;
/* Are we seeking past the last expected packet time?
* If so, don't bother... and mark this source as done
*/
HX_ASSERT(m_llLastExpectedPacketTime < MAX_UINT32);
// XXX HP make sure the source has been initialized otherwise
// m_llLastExpectedPacketTime could be 0 and we could falsely
// mark the source ended
if (m_bInitialized && !mLiveStream && seekTime >= INT64_TO_UINT32(m_llLastExpectedPacketTime))
{
if (m_pSourceInfo && m_pSourceInfo->m_bSeekToLastFrame)
{
seekTime = INT64_TO_UINT32(m_llLastExpectedPacketTime);
}
else
{
m_bSourceEnd = TRUE;
m_bForcedSourceEnd = TRUE;
AdjustClipBandwidthStats(FALSE);
goto cleanup;
}
}
m_bInitialBuffering = TRUE;
m_bForcedSourceEnd = FALSE;
m_uActiveStreams = m_uNumStreams;
m_bIsPreBufferingStarted = FALSE;
m_bIsPreBufferingDone = FALSE;
if (m_nSeeking == 0)
{
m_nSeeking++;
}
#if defined(HELIX_FEATURE_RECORDCONTROL)
if (m_pRecordControl && m_pRecordControl->Seek(seekTime) == HXR_OK &&
m_bPlayFromRecordControl)
{
m_pBufferManager->DoSeek(seekTime, TRUE);
SeekDone(HXR_OK);
}
else
#endif /* HELIX_FEATURE_RECORDCONTROL */
{
m_bSourceEnd = FALSE;
m_pBufferManager->DoSeek(seekTime, FALSE);
if (HXR_OK != m_pFFObject->Seek(seekTime))
{
if (m_nSeeking)
{
m_nSeeking--;
}
}
}
m_llLastFillEndTime = 0;
cleanup:
return HXR_OK;
}
HX_RESULT
HXFileSource::DoPause(void)
{
if (m_bPaused)
{
return HXR_OK;
}
/* Only if it is an external pause */
if (!m_bSourceEnd && !m_bDelayed && m_pBufferManager)
{
m_pBufferManager->DoPause();
}
m_bPaused = TRUE;
return HXR_OK;
}
HX_RESULT
HXFileSource::StartInitialization(void)
{
m_bFastStartInProgress = TRUE;
m_pBufferManager->DoResume();
if (m_pSourceInfo)
{
m_pSourceInfo->Resumed();
}
return HXR_OK;
}
HX_RESULT
HXFileSource::DoResume(void)
{
HX_RESULT theErr = HXR_OK;
m_bFastStartInProgress = FALSE;
/* This may happen if a new source is added from SMIL renderer during
* initialization of exisitng sources. We will eventually call Resume
* on this source once it is initialized in SourceInfo::ProcessIdle
*/
if (!m_bInitialized || (m_pSourceInfo && !m_pSourceInfo->IsInitialized()))
{
return HXR_OK;
}
if (m_bSourceEnd || CanBeResumed())
{
m_bResumePending = FALSE;
if (!m_bSourceEnd)
{
m_pBufferManager->DoResume();
}
// resume the audio streams if the source is added
// while the player is in play mode
// CAUTION: this will cause rewind in audio service
if (m_bFirstResume && m_pPlayer->IsPlaying() &&
m_ulDelay <= m_pPlayer->GetInternalCurrentPlayTime())
{
ResumeAudioStreams();
}
m_bFirstResume = FALSE;
m_bPaused = FALSE;
if (m_pSourceInfo)
{
m_pSourceInfo->Resumed();
}
if (!m_bSourceEnd)
{
theErr = FillBuffers();
}
}
if (!theErr && !m_bIsActive && !m_bDelayed &&
m_pPlayer->GetInternalCurrentPlayTime() >= m_ulDelay)
{
AdjustClipBandwidthStats(TRUE);
}
if (theErr == HXR_AT_END)
{
SetEndOfClip();
theErr = HXR_OK;
}
return theErr;
}
/************************************************************************
* Method:
* IHXPendingStatus::GetStatus
* Purpose:
* Called by the user to get the current pending status from an object
*/
STDMETHODIMP
HXFileSource::GetStatus
(
REF(UINT16) uStatusCode,
REF(IHXBuffer*) pStatusDesc,
REF(UINT16) ulPercentDone
)
{
HX_RESULT hResult = HXR_OK;
IHXPendingStatus* pStatus = NULL;
UINT16 buffer = 100;
UINT16 statusCode = HX_STATUS_READY;
UINT16 percentDone = 0;
uStatusCode = HX_STATUS_READY;
pStatusDesc = 0;
ulPercentDone = 0;
if (m_bDelayed)
{
return HXR_OK;
}
if (m_bSourceEnd)
{
if (!IsRebufferDone())
{
uStatusCode = HX_STATUS_BUFFERING;
ulPercentDone = 99;
}
else
{
if (m_bInitialBuffering)
{
InitialBufferingDone();
}
m_ulLastBufferingReturned = 100;
uStatusCode = HX_STATUS_READY;
}
return HXR_OK;
}
if (m_bInitialized)
{
if (m_bFirstResume)
{
uStatusCode = HX_STATUS_INITIALIZING;
return HXR_OK;
}
m_pBufferManager->GetStatus(uStatusCode,
pStatusDesc,
ulPercentDone);
buffer = ulPercentDone;
/* We only aggregate buffering from a lower level if we are in a buffering mode.
* Reason: Once the initial bufering is done, we go in buffering more ONLY IF the
* renderer tells us that it is in a panic state and we run out of packets.
*/
if (buffer == 100 && !m_bInitialBuffering)
{
// Rebuffer requested by the Renderer might not be
// done yet
if (!IsRebufferDone())
{
uStatusCode = HX_STATUS_BUFFERING;
ulPercentDone = 99;
}
else
{
uStatusCode = HX_STATUS_READY;
}
return HXR_OK;
}
}
if (m_pFFObject)
{
if (HXR_OK != m_pFFObject->QueryInterface(IID_IHXPendingStatus, (void**)&pStatus))
{
goto exit;
}
if (HXR_OK != pStatus->GetStatus(statusCode, pStatusDesc, percentDone))
{
goto exit;
}
}
else if (m_pFileObject)
{
if (HXR_OK != m_pFileObject->QueryInterface(IID_IHXPendingStatus, (void**)&pStatus))
{
goto exit;
}
if (HXR_OK != pStatus->GetStatus(statusCode, pStatusDesc, percentDone))
{
goto exit;
}
}
exit:
if (HX_STATUS_CONTACTING == statusCode)
{
uStatusCode = HX_STATUS_CONTACTING;
ulPercentDone = 0;
}
else if (!m_bInitialized)
{
uStatusCode = HX_STATUS_INITIALIZING;
ulPercentDone = 0;
}
else if (HX_STATUS_READY == statusCode && 100 == buffer)
{
uStatusCode = HX_STATUS_READY;
ulPercentDone = 0;
m_ulLastBufferingReturned = 100;
}
else
{
uStatusCode = HX_STATUS_BUFFERING;
if (HX_STATUS_READY == statusCode)
{
ulPercentDone = (UINT16)buffer;
}
else
{
ulPercentDone = (UINT16)((buffer + percentDone) * 0.5);
}
// Do not go back
if (ulPercentDone < m_ulLastBufferingReturned && m_ulLastBufferingReturned != 100)
{
ulPercentDone = (UINT16) m_ulLastBufferingReturned;
}
else
{
m_ulLastBufferingReturned = ulPercentDone;
}
}
HX_RELEASE(pStatus);
ulPercentDone = ulPercentDone <= 100 ? (UINT16)ulPercentDone : 100;
if (m_bInitialBuffering && HX_STATUS_READY == uStatusCode)
{
InitialBufferingDone();
}
/* If we had a delayed start, we do not want to show that we are
* in buffering state UNLESS it is really time to give out packets
* and we do not have
*/
if (m_bInitialized && m_ulDelay > 0 &&
uStatusCode == HX_STATUS_BUFFERING &&
ulPercentDone < 100)
{
UINT32 ulCurrentTime = m_pPlayer->GetInternalCurrentPlayTime();
if ((ulCurrentTime + MIN_BUFFERTIME_BEFORE_DELAY) < m_ulDelay)
{
ulPercentDone = 100;
}
}
return hResult;
}
UINT16
HXFileSource::GetNumStreams(void)
{
HX_ASSERT(m_bInitialized);
return m_uNumStreams;
}
HX_RESULT
HXFileSource::GetStreamInfo(ULONG32 ulStreamNumber,
STREAM_INFO*& theStreamInfo)
{
HX_RESULT theErr = HXR_OK;
STREAM_INFO* lpStreamInfo = 0;
if (!mStreamInfoTable->Lookup((LONG32)ulStreamNumber, (void *&)lpStreamInfo))
{
theErr = HXR_INVALID_PARAMETER;
}
theStreamInfo = lpStreamInfo;
return theErr;
}
HX_RESULT
HXFileSource::GetEvent(UINT16 usStreamNumber, CHXEvent*& theEvent)
{
HX_RESULT theErr = HXR_OK;
HX_TRACE("HXFileSource::GetEvent");
theEvent = 0;
if (!m_bInitialized)
{
return HXR_NOT_INITIALIZED;
}
if (mLastError != HXR_OK)
{
return mLastError;
}
if (m_bPaused && m_bDelayed)
{
if (TryResume())
{
m_pPlayer->RegisterSourcesDone();
DoResume();
}
else
{
return HXR_NO_DATA;
}
}
STREAM_INFO * lpStreamInfo;
if (!mStreamInfoTable->Lookup((LONG32) usStreamNumber, (void *&) lpStreamInfo))
{
theErr = HXR_INVALID_PARAMETER;
return theErr;
}
#if defined(HELIX_FEATURE_RECORDCONTROL)
if (m_bPlayFromRecordControl && m_pRecordControl)
{
IHXPacket* pPacket = NULL;
HX_ASSERT(m_pRecordControl);
theErr = m_pRecordControl->GetPacket(usStreamNumber, pPacket);
if(theErr == HXR_OK)
{
UINT32 streamPreRoll = max(lpStreamInfo->BufferingState().GetMinPrerollInMs(),1000);
INT64 llPacketTime =
lpStreamInfo->BufferingState().CreateINT64Timestamp(pPacket->GetTime());
theEvent = new CHXEvent(pPacket,
GetEventBeginTime(llPacketTime,
streamPreRoll));
if(theEvent)
theEvent->SetTimeOffset(m_ulStartTime - m_ulDelay);
else
theErr = HXR_OUTOFMEMORY;
if(m_pBufferManager)
m_pBufferManager->UpdateCounters(pPacket);
HX_RELEASE(pPacket);
}
else
{
if(theErr == HXR_NO_DATA && (m_bSourceEnd || lpStreamInfo->m_bSrcStreamDone))
theErr = HXR_AT_END;
if(theErr == HXR_NO_DATA)
{
if (lpStreamInfo->m_unNeeded > 0 &&
lpStreamInfo->m_unNeeded != lpStreamInfo->m_unAvailable)
{
// Re-initialize buffering
m_pBufferManager->ReBuffer();
FillBuffers();
theErr = HXR_BUFFERING;
}
}
}
return theErr;
}
#endif /* HELIX_FEATURE_RECORDCONTROL */
// get the packet list for this stream
CHXEventList * lEventList = &lpStreamInfo->m_EventList;
// do we need to fill buffers...
if (lEventList->GetNumEvents() == 0)
{
theErr = FillBuffers();
if (theErr == HXR_AT_END)
{
SetEndOfClip();
theErr = HXR_OK;
}
// check if we have packets now...
if (!theErr && lEventList->GetNumEvents() == 0)
{
if (m_bSourceEnd || lpStreamInfo->m_bSrcStreamDone)
{
return HXR_AT_END;
}
else
{
if (lpStreamInfo->m_unNeeded > 0 &&
lpStreamInfo->m_unNeeded != lpStreamInfo->m_unAvailable)
{
// Re-initialize buffering
m_pBufferManager->ReBuffer();
FillBuffers();
return HXR_BUFFERING;
}
return HXR_NO_DATA;
}
}
}
if (!theErr)
{
// this event will be deleted by the player...
theEvent = lEventList->RemoveHead();
}
#ifdef LOSS_HACK
if (m_ulLossHack > 0 && ((UINT32) (rand() % 100) < m_ulLossHack) &&
!theErr && theEvent && !(theEvent->GetPacket())->IsLost())
{
GenerateFakeLostPacket(theEvent);
/* Update the stats */
if (lpStreamInfo->m_ulReceived > 0)
{
lpStreamInfo->m_ulReceived--;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -