📄 hxbufstate.cpp
字号:
* server on the local machine.
*/
if (ulElapsedTime == 0)
{
if (m_ulCurrentBufferingInMs >= m_ulMinimumPrerollInMs)
{
m_ulRemainingToBufferInMs = 0;
}
}
else
{
CalcRemainingToBufferInMs(ulElapsedTime);
}
}
}
else
{
/* bIsBufferedPlayMode == FALSE */
if (m_ulRemainingToBufferInMs)
{
CalcRemainingToBufferInMs();
}
}
}
void HXBufferingState::UpdateTransportStats(INT64 llLowTSAtTransport,
INT64 llHighTSAtTransport,
ULONG32 ulBytesAtTransport,
BOOL bDoneAtTransport)
{
m_llLowestTimestampAtTransport = llLowTSAtTransport;
m_llHighestTimestampAtTransport = llHighTSAtTransport;
m_ulNumBytesAtTransport = ulBytesAtTransport;
m_bDoneAtTransport = bDoneAtTransport;
}
HX_RESULT HXBufferingState::GetBufferingStats(REF(INT64) llLowTimestamp,
REF(INT64) llHighTimestamp,
REF(UINT32) ulBytesBuffered,
BOOL bUseTransportStats)
{
HX_RESULT res = HXR_NO_DATA;
if (!m_bIsFirstPacket)
{
if (!m_pktInfo.IsEmpty())
{
HXBufferedPktInfo* pPktInfo =
(HXBufferedPktInfo*)m_pktInfo.GetHead();
llLowTimestamp = pPktInfo->Timestamp();
}
else
{
llLowTimestamp = m_llHighestTimeStamp;
}
llHighTimestamp = m_llHighestTimeStamp;
ulBytesBuffered = GetBufferedData();
if (bUseTransportStats)
{
if (m_llHighestTimestampAtTransport > llHighTimestamp)
{
llHighTimestamp = m_llHighestTimestampAtTransport;
}
ulBytesBuffered += m_ulNumBytesAtTransport;
}
res = HXR_OK;
}
return res;
}
void HXBufferingState::GetExcessBufferInfo(INT64 llTheLowestTS,
INT64 llTheHighestTS,
BOOL bIsSeekPerformed,
REF(UINT32) ulRemainToBufferInMs,
REF(UINT32) ulRemainToBuffer,
REF(UINT32) ulExcessBufferInMs,
REF(UINT32) ulExcessBuffer,
REF(UINT32) ulExcessForThisStreamInMs,
REF(UINT32) ulExcessForThisStream)
{
UINT32 ulCurBufInMs = 0;
UINT32 ulRemainForThisStreamInMs = 0;
UINT32 ulRemainForThisStream = 0;
ulExcessForThisStreamInMs = 0;
ulExcessForThisStream = 0;
if (m_ulNumBytesAtTransport > 0)
{
HX_ASSERT((llTheHighestTS - m_llLowestTimestampAtTransport) < MAX_TIMESTAMP_GAP);
ulCurBufInMs = INT64_TO_UINT32(llTheHighestTS -
m_llLowestTimestampAtTransport);
}
else
{
HX_ASSERT((llTheHighestTS - llTheLowestTS) < MAX_TIMESTAMP_GAP);
ulCurBufInMs = INT64_TO_UINT32(llTheHighestTS - llTheLowestTS);
}
if (ulCurBufInMs <= m_ulMinimumBufferingInMs)
{
ulRemainForThisStreamInMs = m_ulMinimumBufferingInMs - ulCurBufInMs;
}
else
{
ulExcessForThisStreamInMs = ulCurBufInMs - m_ulMinimumBufferingInMs;
}
if (m_ulNumBytesAtTransport <= m_ulMinimumBuffering)
{
ulRemainForThisStream =
m_ulMinimumBuffering - m_ulNumBytesAtTransport;
}
else
{
ulExcessForThisStream = m_ulNumBytesAtTransport - m_ulMinimumBuffering;
}
BOOL bHasPreroll = HasPreroll(bIsSeekPerformed);
BOOL bHasPredata = HasPredata(bIsSeekPerformed);
// satisfy the preroll (by default + pre-set)
if (!bHasPredata || bHasPreroll)
{
if (ulRemainToBufferInMs < ulRemainForThisStreamInMs)
{
ulRemainToBufferInMs = ulRemainForThisStreamInMs;
}
if (ulExcessBufferInMs < ulExcessForThisStreamInMs)
{
ulExcessBufferInMs = ulExcessForThisStreamInMs;
}
}
// satisfy the predata
if (bHasPredata)
{
ulRemainToBuffer += ulRemainForThisStream;
ulExcessBuffer += ulExcessForThisStream;
}
}
void HXBufferingState::OnTimeSync(UINT32 ulCurrentTime)
{
// 0xFA .. 0xFF [roll over] (0x01)
if (m_ulLastTimeSync > ulCurrentTime &&
((m_ulLastTimeSync - ulCurrentTime) > MAX_TIMESTAMP_GAP))
{
m_ulTimeSyncRollOver++;
}
m_ulLastTimeSync = ulCurrentTime;
m_llCurrentPlaybackTime = CreateINT64Timesync(ulCurrentTime);
}
void HXBufferingState::SetMinPrerollInMs(ULONG32 ulMinPrerollInMs,
ULONG32 ulMinBufferingInMs)
{
m_ulMinimumPrerollInMs = ulMinPrerollInMs;
m_ulMinimumBufferingInMs = ulMinBufferingInMs;
m_ulRemainingToBufferInMs = m_ulMinimumBufferingInMs;
}
void HXBufferingState::SetMinPreroll()
{
SetMinPreroll(MsToBytes(m_ulMinimumPrerollInMs,
m_ulAvgBandwidth),
m_ulAvgBandwidth);
}
void HXBufferingState::SetMinPreroll(UINT32 ulMinimumPredata,
UINT32 ulBandwidth)
{
HX_ASSERT(m_ulMinimumPrerollInMs >= m_ulPreroll);
UINT32 ulExtraBufferingInMs = m_ulMinimumPrerollInMs - m_ulPreroll;
/* Get current bandiwidth from asm */
m_ulMinimumPreroll = (ulMinimumPredata +
MsToBytes(ulExtraBufferingInMs,
ulBandwidth));
// There is no buffered or perfect play with MIN_HEAP on.
#if defined(HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
m_ulMinimumBuffering = m_ulMinimumPreroll;
#else
ulExtraBufferingInMs = m_ulMinimumBufferingInMs - m_ulPreroll;
m_ulMinimumBuffering = (ulMinimumPredata +
MsToBytes(ulExtraBufferingInMs,
ulBandwidth));
#endif
m_ulRemainingToBuffer = m_ulMinimumBuffering;
m_ulCurrentBuffering = 0;
}
void HXBufferingState::UpdateMinPredata()
{
UINT32 ulMinimumPredata = m_ulPredata;
UINT32 ulBandwidth = m_ulAvgBandwidth;
#if defined(HELIX_FEATURE_ASM)
// no ASMProps in AutoConfig
HX_ASSERT(m_pASMProps);
if (m_pASMProps)
{
UINT32 ulTmp;
if (HXR_OK == m_pASMProps->GetPreData(ulTmp))
{
ulMinimumPredata = ulTmp;
}
if (HXR_OK == m_pASMProps->GetBandwidth(ulTmp))
{
ulBandwidth = ulTmp;
}
}
#endif /* HELIX_FEATURE_ASM */
SetMinPreroll(ulMinimumPredata, ulBandwidth);
}
void HXBufferingState::UpdateCurrentBufferingInMs(INT64 llLowestTimeStamp,
INT64 llHighestTimeStamp)
{
INT64 llLowTimestamp = m_llLowestTimeStamp;
if (m_bIsFirstPacket)
{
/* use the reference stream's lowest timestamp for calculation */
llLowTimestamp = llLowestTimeStamp;
}
if (llHighestTimeStamp > llLowTimestamp)
{
// if the stream has been continuesly playing for 49 days
// we will set m_ulCurrentBufferingInMs to MAX_UINT32
if (llHighestTimeStamp - llLowTimestamp > MAX_UINT32)
{
m_ulCurrentBufferingInMs = MAX_UINT32;
}
else
{
m_ulCurrentBufferingInMs =
INT64_TO_UINT32(llHighestTimeStamp - llLowTimestamp);
}
}
}
ULONG32 HXBufferingState::MsToBytes(ULONG32 ulValueInMs, ULONG32 ulBw) const
{
return (ulValueInMs * (ulBw / 8)) / 1000;
}
void HXBufferingState::CalcRemainingToBufferInMs()
{
m_ulRemainingToBufferInMs = CalcRemaining(m_ulMinimumBufferingInMs,
m_ulCurrentBufferingInMs,
0,
0);
}
void HXBufferingState::CalcRemainingToBufferInMs(ULONG32 ulElapsedTime)
{
m_ulRemainingToBufferInMs = CalcRemaining(m_ulMinimumBufferingInMs,
m_ulCurrentBufferingInMs,
m_ulMinimumPrerollInMs,
ulElapsedTime);
}
void HXBufferingState::CalcRemainingToBuffer()
{
m_ulRemainingToBuffer = CalcRemaining(m_ulMinimumBuffering,
m_ulCurrentBuffering,
0,
0);
}
void HXBufferingState::CalcRemainingToBuffer(ULONG32 ulDenom)
{
m_ulRemainingToBuffer = CalcRemaining(m_ulMinimumBuffering,
m_ulCurrentBuffering,
m_ulMinimumPreroll,
ulDenom);
}
UINT32 HXBufferingState::CalcRemaining(UINT32 ulMinimumBuffering,
UINT32 ulCurrentBuffering,
UINT32 ulMinimumPreroll,
UINT32 ulDenom) const
{
UINT32 ulRemainingToBuffer = 0;
if (ulMinimumBuffering > ulCurrentBuffering)
{
ulRemainingToBuffer = ulMinimumBuffering - ulCurrentBuffering;
}
if (ulDenom)
{
UINT32 ulBufferWhilePlaying = ulRemainingToBuffer;
/*
* Buffers during playback = X*X/Y + X*(X/Y)^2 + X*(X/Y)^3 + ....
* = X*X/Y (1 + X/Y + (X/Y)^2 + ....)
*
* = X*X/Y ( 1 / (1 - X/Y)) IFF X/Y < 1 i.e. X < Y
*
* ELSE We have enough data... Satisfy preroll
*/
/* Add a fudge factor of 10% */
ulDenom = (UINT32) (ulDenom * 1.10);
if (ulCurrentBuffering < ulDenom)
{
double x = ulCurrentBuffering;
double y = ulDenom;
ulBufferWhilePlaying = (UINT32) (((x * x) / y) * (1. / (1. - x / y)));
}
if (ulBufferWhilePlaying < ulRemainingToBuffer)
{
ulRemainingToBuffer -= ulBufferWhilePlaying;
}
else if (ulCurrentBuffering >= ulMinimumPreroll)
{
ulRemainingToBuffer = 0;
}
}
return ulRemainingToBuffer;
}
void HXBufferingState::SetAvgBWToASMBw()
{
UINT32 ulBandwidth = 0;
if (m_pASMProps &&
m_pASMProps->GetBandwidth(ulBandwidth) == HXR_OK)
{
m_ulAvgBandwidth = ulBandwidth;
}
}
void HXBufferingState::ClearPktInfo()
{
m_ulBufferedData = 0;
while(!m_pktInfo.IsEmpty())
{
HXBufferedPktInfo* pInfo = (HXBufferedPktInfo*)m_pktInfo.RemoveHead();
delete pInfo;
}
}
void HXBufferingState::AddPktInfo(INT64 llTimestamp, UINT32 ulPacketSize)
{
// Subtract off the first live packet timestamp.
// If not live, then m_llFirstLivePacketTimeStamp is 0.
llTimestamp -= m_llFirstLivePacketTimestamp;
// Create the HXBufferedPktInfo class
HXBufferedPktInfo* pPktInfo = new HXBufferedPktInfo(llTimestamp,
ulPacketSize);
if (pPktInfo)
{
m_pktInfo.AddTail(pPktInfo);
m_ulBufferedData += ulPacketSize;
}
// purge the old packet info data
// this keeps the list short and prevents the Symbian
// allocator from freaking out
(void)GetBufferedData();
}
UINT32 HXBufferingState::GetBufferedData()
{
BOOL bDone = m_pktInfo.IsEmpty();
// Remove all packet info that is past due
// and subtract their sizes from our buffering total
while(!bDone)
{
HXBufferedPktInfo* pPktInfo = (HXBufferedPktInfo*)m_pktInfo.GetHead();
if (pPktInfo->Timestamp() <= m_llCurrentPlaybackTime)
{
m_ulBufferedData -= pPktInfo->Size();
m_pktInfo.RemoveHead();
delete pPktInfo;
bDone = m_pktInfo.IsEmpty();
}
else
{
bDone = TRUE;
}
}
return m_ulBufferedData;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -