📄 buffmgr.cpp
字号:
!(pPacket->GetASMFlags() & HX_ASM_DROPPED_PKT))
{
// Ignore all lost packets that aren't dropped packets
return hr;
}
ulStreamNum = pPacket->GetStreamNumber();
if (!m_pStreamInfoTable->Lookup(ulStreamNum, (void*&)pStreamInfo))
{
return HXR_INVALID_PARAMETER;
}
pThisStreamInfo = pStreamInfo;
pBuffer = pPacket->GetBuffer();
if (pBuffer)
{
ulBufferSize = pBuffer->GetSize();
}
HX_RELEASE(pBuffer);
ulBufferTime = pPacket->GetTime();
/* Set Buffering start time for all streams */
if (m_bBufferStartTimeToBeSet)
{
m_bBufferStartTimeToBeSet = FALSE;
m_ulBufferingStartTime = ulCurrentTime;
}
ulElapsedTime = GetElapsedTime(ulCurrentTime);
BOOL bIsBufferedPlayMode = (m_bPerfectPlay || m_bBufferedPlay ||
(m_bLocalPlayback && !m_pParent->IsLive()));
pStreamInfo->BufferingState().OnPacket(ulBufferTime, ulBufferSize,
ulElapsedTime,
m_pParent->IsLive(),
bIsBufferedPlayMode);
llActualTimeStamp =
pStreamInfo->BufferingState().CreateINT64Timestamp(ulBufferTime);
// time based preroll by default
UpdateHighestTimestamps(llActualTimeStamp, pStreamInfo);
INT64 llLowRefTS = pThisStreamInfo->BufferingState().LowTS();
// adjust each stream preroll based on the hightest time stamp
for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
{
pStreamInfo = (STREAM_INFO*) (*i);
BOOL bIsTimestampDelivery = FALSE;
if (pStreamInfo->m_pStream &&
pStreamInfo->m_pStream->IsTimeStampDelivery())
{
bIsTimestampDelivery = TRUE;
}
pStreamInfo->BufferingState().UpdateBufferingInMs(llLowRefTS,
m_llHighestTimeStamp,
bIsBufferedPlayMode,
bIsTimestampDelivery,
ulElapsedTime);
}
return hr;
}
HX_RESULT
CBufferManager::GetStatus(REF(UINT16) uStatusCode,
REF(IHXBuffer*) pStatusDesc,
REF(UINT16) uPercentDone)
{
STREAM_INFO* pStreamInfo = NULL;
CHXMapLongToObj::Iterator i;
uStatusCode = HX_STATUS_READY;
pStatusDesc = NULL;
uPercentDone = 0;
// collect from each streams
for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
{
pStreamInfo = (STREAM_INFO*) (*i);
uPercentDone += pStreamInfo->BufferingState().GetPercentDone(m_bIsSeekPerformed);
}
// average them
uPercentDone = uPercentDone / m_pStreamInfoTable->GetCount();
if (uPercentDone >= 100)
{
uPercentDone = 100;
m_state = BUFFMGR_READY;
}
else
{
uStatusCode = HX_STATUS_BUFFERING;
}
// DEBUG_OUT(m_pParent->m_pPlayer, DOL_GENERIC, (s,
// "BuffMgr::GetStatus: %p Status: %s uPercentDone: %lu ", this,
// (uStatusCode == HX_STATUS_BUFFERING ? "HX_STATUS_BUFFERING" : "HX_STATUS_READY" ),
// uPercentDone));
return HXR_OK;
}
HX_RESULT
CBufferManager::GetRemainToBuffer(REF(UINT32) ulRemainToBufferInMs,
REF(UINT32) ulRemainToBuffer)
{
STREAM_INFO* pStreamInfo = NULL;
ulRemainToBufferInMs = 0;
ulRemainToBuffer = 0;
CHXMapLongToObj::Iterator i;
// caculate each stream
for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
{
pStreamInfo = (STREAM_INFO*) (*i);
BOOL bHasPreroll =
pStreamInfo->BufferingState().HasPreroll(m_bIsSeekPerformed);
BOOL bHasPredata =
pStreamInfo->BufferingState().HasPredata(m_bIsSeekPerformed);
UINT32 ulRemainInMs;
UINT32 ulRemain;
pStreamInfo->BufferingState().GetRemainToBuffer(ulRemainInMs,
ulRemain);
// satisfy the preroll (by default + pre-set)
if ((!bHasPredata || bHasPreroll) &&
(ulRemainToBufferInMs < ulRemainInMs))
{
ulRemainToBufferInMs = ulRemainInMs;
}
// satisfy the predata
if (bHasPredata)
{
ulRemainToBuffer += ulRemain;
}
}
return HXR_OK;
}
HX_RESULT
CBufferManager::GetMaximumPreroll(REF(UINT32) ulMaximumPrerollInMs)
{
STREAM_INFO* pStreamInfo = NULL;
CHXMapLongToObj::Iterator i;
ulMaximumPrerollInMs = 0;
// get max. preroll among the streams
for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
{
pStreamInfo = (STREAM_INFO*) (*i);
UINT32 ulMinPrerollInMs =
pStreamInfo->BufferingState().GetMinPrerollInMs();
if (ulMaximumPrerollInMs < ulMinPrerollInMs)
{
ulMaximumPrerollInMs = ulMinPrerollInMs;
}
}
return HXR_OK;
}
HX_RESULT
CBufferManager::GetExcessBufferInfo(REF(UINT32) ulRemainToBufferInMs,
REF(UINT32) ulRemainToBuffer,
REF(UINT32) ulExcessBufferInMs,
REF(UINT32) ulExcessBuffer,
REF(BOOL) bValidInfo,
REF(UINT32) ulActualExcessBufferInMs,
REF(UINT32) ulActualExcessBuffer)
{
STREAM_INFO* pStreamInfo = NULL;
INT64 llTheLowestTS = 0;
INT64 llTheHighestTS = 0;
BOOL bIsFirst = TRUE;
STREAM_INFO* pNonEmptyStreamInfo = NULL;
ulRemainToBufferInMs = 0;
ulRemainToBuffer = 0;
ulExcessBufferInMs = 0;
ulExcessBuffer = 0;
bValidInfo = FALSE;
ulActualExcessBufferInMs= 0;
ulActualExcessBuffer = 0;
CHXMapLongToObj::Iterator i;
/*
* - Update transport stats for each stream.
* - Find the lowest and highest timestamps across all streams
* - Keep track of the stream with the lowest timestamp and is
* buffering data
*/
for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
{
pStreamInfo = (STREAM_INFO*) (*i);
INT64 llLowestTimestampAtTransport = 0;
INT64 llHighestTimestampAtTransport = 0;
ULONG32 ulNumBytesAtTransport = 0;
BOOL bDoneAtTransport = FALSE;
m_pParent->GetCurrentBuffering(pStreamInfo->m_uStreamNumber,
llLowestTimestampAtTransport,
llHighestTimestampAtTransport,
ulNumBytesAtTransport,
bDoneAtTransport);
pStreamInfo->BufferingState().UpdateTransportStats(
llLowestTimestampAtTransport,
llHighestTimestampAtTransport,
ulNumBytesAtTransport,
bDoneAtTransport);
if (ulNumBytesAtTransport > 0)
{
if (bIsFirst)
{
bIsFirst = FALSE;
llTheLowestTS = llLowestTimestampAtTransport;
llTheHighestTS = llHighestTimestampAtTransport;
pNonEmptyStreamInfo = pStreamInfo;
}
else
{
if (llTheLowestTS > llLowestTimestampAtTransport)
{
llTheLowestTS = llLowestTimestampAtTransport;
/* This is the stream with the lowest timestamp */
pNonEmptyStreamInfo = pStreamInfo;
}
if (llTheHighestTS < llHighestTimestampAtTransport)
{
llTheHighestTS = llHighestTimestampAtTransport;
}
}
}
}
/* If none of the streams have any data buffered at the transport layer,
* return.
*/
if (!pNonEmptyStreamInfo)
{
return HXR_OK;
}
for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
{
pStreamInfo = (STREAM_INFO*) (*i);
UINT32 ulExcessForThisStreamInMs = 0;
UINT32 ulExcessForThisStream = 0;
pStreamInfo->BufferingState().GetExcessBufferInfo(llTheLowestTS,
llTheHighestTS,
m_bIsSeekPerformed,
ulRemainToBufferInMs,
ulRemainToBuffer,
ulExcessBufferInMs,
ulExcessBuffer,
ulExcessForThisStreamInMs,
ulExcessForThisStream);
/* Update Actual Values Regardless of Preroll / PreData */
ulActualExcessBuffer += ulExcessForThisStream;
if (ulActualExcessBufferInMs < ulExcessForThisStreamInMs)
{
ulActualExcessBufferInMs = ulExcessForThisStreamInMs;
}
}
bValidInfo = TRUE;
if (ulRemainToBufferInMs >= ulExcessBufferInMs)
{
ulRemainToBufferInMs -= ulExcessBufferInMs;
ulExcessBufferInMs = 0;
}
else
{
ulExcessBufferInMs -= ulRemainToBufferInMs;
ulRemainToBufferInMs = 0;
}
if (ulRemainToBuffer > 0)
{
ulExcessBuffer = 0;
}
return HXR_OK;
}
void
CBufferManager::EnterBufferedPlay(void)
{
#if !defined(HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
if (!m_bBufferedPlay && !m_bPerfectPlay)
{
m_bBufferedPlay = TRUE;
UINT32 ulRemainToBufferInMs = 0;
UINT32 ulRemainToBuffer = 0;
GetRemainToBuffer(ulRemainToBufferInMs, ulRemainToBuffer);
/* If we are not done with buffering yet, update the buffering
* calc now!
*/
if (ulRemainToBufferInMs > 0 ||
ulRemainToBuffer > 0)
{
UpdateMinimumPreroll(FALSE);
}
else
{
m_bBufferCalcToBeChanged = TRUE;
}
}
#endif // (HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
}
void
CBufferManager::LeaveBufferedPlay(void)
{
#if !defined(HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
if (m_bBufferedPlay)
{
m_bBufferCalcToBeChanged = TRUE;
m_bBufferedPlay = FALSE;
}
#endif // (HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
}
UINT32 CBufferManager::GetElapsedTime(UINT32 ulCurrentTime)
{
UINT32 ulElapsedTime =
CALCULATE_ELAPSED_TICKS(m_ulBufferingStartTime, ulCurrentTime);
if (m_ulTotalPauseTime > 0)
{
HX_ASSERT(ulElapsedTime >= m_ulTotalPauseTime);
ulElapsedTime = ulElapsedTime > m_ulTotalPauseTime ?
ulElapsedTime - m_ulTotalPauseTime : 0;
}
return ulElapsedTime;
}
void CBufferManager::UpdateHighestTimestamps(INT64 llActualTimeStamp,
STREAM_INFO* pStreamInfo)
{
// we apply the highest packet time-stamp to every stream
// to solve infinite buffering
if (m_llHighestTimeStamp < llActualTimeStamp)
{
m_llHighestTimeStamp = llActualTimeStamp;
}
}
void CBufferManager::SetPerfectPlay(BOOL bPerfectPlay)
{
m_bPerfectPlay = bPerfectPlay;
if (m_pParent->IsLive())
{
m_bPerfectPlay = FALSE;
m_bBufferedPlay = FALSE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -