hxbufstate.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:22k
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: RCSL 1.0/RPSL 1.0
- *
- * Portions Copyright (c) 1995-2003 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file, are
- * subject to the current version of the RealNetworks Public Source License
- * Version 1.0 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the RealNetworks Community Source License Version 1.0
- * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
- * in which case the RCSL will apply. You may also obtain the license terms
- * directly from RealNetworks. You may not use this file except in
- * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
- * applicable to this file, the RCSL. Please see the applicable RPSL or
- * RCSL for the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the portions
- * it created.
- *
- * This file, and the files included with this file, is distributed and made
- * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #include "hxbufstate.h"
- #include "hxassert.h"
- class HXBufferedPktInfo
- {
- public:
- HXBufferedPktInfo(INT64 llTimestamp, UINT32 ulSize);
- INT64 Timestamp() const { return m_llTimestamp;}
- UINT32 Size() const { return m_ulSize;}
- private:
- INT64 m_llTimestamp;
- UINT32 m_ulSize;
- };
- inline
- HXBufferedPktInfo::HXBufferedPktInfo(INT64 llTimestamp,
- UINT32 ulSize) :
- m_llTimestamp(llTimestamp),
- m_ulSize(ulSize)
- {}
- HXBufferingState::HXBufferingState() :
- m_ulPreroll(0)
- , m_ulPredata(0)
- , m_ulMinimumPrerollInMs(0)
- , m_ulMinimumPreroll(0)
- , m_ulMinimumBufferingInMs(0)
- , m_ulMinimumBuffering(0)
- , m_ulRemainingToBufferInMs(0)
- , m_ulRemainingToBuffer(0)
- , m_ulCurrentBufferingInMs(0)
- , m_ulCurrentBuffering(0)
- , m_bIsFirstPacket(TRUE)
- , m_preDataAtStart(FALSE)
- , m_prerollAtStart(FALSE)
- , m_preDataAfterSeek(FALSE)
- , m_prerollAfterSeek(FALSE)
- , m_llLowestTimeStamp(0)
- , m_llHighestTimeStamp(0)
- , m_llLowestTimestampAtTransport(0)
- , m_llHighestTimestampAtTransport(0)
- , m_ulNumBytesAtTransport(0)
- , m_bDoneAtTransport(FALSE)
- , m_ulTSRollOver(0)
- , m_ulLastPacketTimeStamp(0)
- , m_ulAvgBandwidth(0)
- , m_pASMProps(NULL)
- , m_llCurrentPlaybackTime(0)
- , m_ulBufferedData(0)
- , m_ulLastTimeSync(0)
- , m_llFirstLivePacketTimestamp(0)
- , m_ulTimeSyncRollOver(0)
- {}
- HXBufferingState::~HXBufferingState()
- {
- HX_RELEASE(m_pASMProps);
- ClearPktInfo();
- }
- void HXBufferingState::OnStreamHeader(UINT32 ulPreroll,
- UINT32 ulPredata,
- BOOL preDataAtStart,
- BOOL preDataAfterSeek,
- BOOL prerollAtStart,
- BOOL prerollAfterSeek,
- ULONG32 ulAvgBitRate)
- {
- m_ulPreroll = ulPreroll;
- m_ulPredata = ulPredata;
- m_preDataAtStart = preDataAtStart;
- m_preDataAfterSeek = preDataAfterSeek;
- m_prerollAtStart = prerollAtStart;
- m_prerollAfterSeek = prerollAfterSeek;
- m_ulAvgBandwidth = ulAvgBitRate;
- }
- void HXBufferingState::OnStream(IUnknown* pStream)
- {
- HX_RELEASE(m_pASMProps);
- if (pStream)
- {
- pStream->QueryInterface(IID_IHXASMProps, (void**) &m_pASMProps);
- }
- }
- void HXBufferingState::Init(ULONG32 ulPerfectPlayTime)
- {
- SetMinPrerollInMs(m_ulPreroll, m_ulPreroll + ulPerfectPlayTime);
- SetMinPreroll();
- }
- void HXBufferingState::SetMinimumPreroll(UINT32 ulSourcePreroll,
- UINT32 ulInitialAudioPreroll,
- UINT32 ulPerfectPlayTime,
- BOOL bIsRebuffering)
- {
- UINT32 ulMinimumPreroll = m_ulPreroll;
-
- ulMinimumPreroll += ulInitialAudioPreroll;
-
- if (ulMinimumPreroll < ulSourcePreroll)
- {
- ulMinimumPreroll = ulSourcePreroll;
- }
-
- SetMinPrerollInMs(ulMinimumPreroll,
- ulMinimumPreroll + ulPerfectPlayTime);
- m_ulCurrentBufferingInMs = 0;
- /* If we have received at lest one packet for this stream,
- * mark the lowest timestamp to be the
- * last packet timstamp to reset buffering calculations
- */
- if (bIsRebuffering && !m_bIsFirstPacket)
- {
- m_bIsFirstPacket = TRUE;
- m_llLowestTimeStamp =
- CAST_TO_INT64 (m_ulTSRollOver) * CAST_TO_INT64 MAX_UINT32 + CAST_TO_INT64 (m_ulLastPacketTimeStamp);
- }
-
- UpdateMinPredata();
- }
- void HXBufferingState::Stop()
- {
- m_ulRemainingToBufferInMs = 0;
- m_ulRemainingToBuffer = 0;
- }
- void HXBufferingState::Reset(BOOL bIsSeeking, UINT32 ulSeekTime)
- {
- m_ulRemainingToBufferInMs = m_ulMinimumBufferingInMs;
- m_ulRemainingToBuffer = m_ulMinimumBuffering;
- m_ulCurrentBufferingInMs = 0;
- m_ulCurrentBuffering = 0;
- m_ulTSRollOver = 0;
- m_ulLastPacketTimeStamp = 0;
- m_bIsFirstPacket = TRUE;
- ClearPktInfo();
- if (bIsSeeking)
- {
- m_llLowestTimeStamp = CAST_TO_INT64 ulSeekTime;
- m_llHighestTimeStamp = CAST_TO_INT64 ulSeekTime;
- }
- }
- void HXBufferingState::GetRemainToBuffer(REF(UINT32) ulRemainToBufferInMs,
- REF(UINT32) ulRemainToBuffer)
- {
- ulRemainToBufferInMs = m_ulRemainingToBufferInMs;
- ulRemainToBuffer = m_ulRemainingToBuffer;
- }
- UINT16 HXBufferingState::GetPercentDone(BOOL bIsSeekPerformed)
- {
- UINT16 uTotalPercentDone = 100;
- UINT16 uPreDataPercentDone = 100;
- UINT16 uPrerollPercentDone = 100;
- BOOL bHasPreroll;
- BOOL bHasPredata;
- BOOL bNeedsData = FALSE;
- if (!bIsSeekPerformed)
- {
- // start/rebuffer mode
- bHasPreroll = m_prerollAtStart;
- bHasPredata = m_preDataAtStart;
- }
- else
- {
- // seek mode
- bHasPreroll = m_prerollAfterSeek;
- bHasPredata = m_preDataAfterSeek;
- }
- // satisfy the preroll (by default + pre-set)
- if (!bHasPredata || bHasPreroll)
- {
- // percent done on preroll
- if (m_ulMinimumBufferingInMs)
- {
- uPrerollPercentDone =
- ((m_ulMinimumBufferingInMs-m_ulRemainingToBufferInMs ) * 100) /
- m_ulMinimumBufferingInMs;
- }
-
- uTotalPercentDone = uPrerollPercentDone;
- bNeedsData = (m_ulRemainingToBufferInMs > 0);
- }
- // satisfy the predata
- if (bHasPredata)
- {
- // percent done on predata
- if (m_ulMinimumBuffering)
- {
- uPreDataPercentDone =
- ((m_ulMinimumBuffering - m_ulRemainingToBuffer ) * 100) /
- m_ulMinimumBuffering;
- }
-
- uTotalPercentDone = uPreDataPercentDone;
- bNeedsData = (m_ulRemainingToBuffer > 0);
- }
- if (bHasPredata && bHasPreroll)
- {
- uTotalPercentDone = (uPrerollPercentDone + uPreDataPercentDone) / 2;
- }
- else if ((bIsSeekPerformed) &&
- (uTotalPercentDone == 100) &&
- (bNeedsData))
- {
- uTotalPercentDone = 99;
- }
- return uTotalPercentDone;
- }
- void HXBufferingState::UpdatePreroll(ULONG32 ulPreroll)
- {
- UINT32 ulExtraPrerollInMs = m_ulMinimumPrerollInMs - m_ulPreroll;
- UINT32 ulExtraBufferingInMs = m_ulMinimumBufferingInMs - m_ulPreroll;
-
- SetPreroll(ulPreroll);
- SetMinPrerollInMs(ulPreroll + ulExtraPrerollInMs,
- ulPreroll + ulExtraBufferingInMs);
- SetMinPreroll();
- // Notice that we don't call ClearCurrentBufferingInMs()
- // or ClearCurrentBuffering(). This allows us to count
- // any data we have already received as part of the
- // new preroll
- CalcRemainingToBufferInMs();
- CalcRemainingToBuffer();
- }
- INT64 HXBufferingState::CreateINT64Timestamp(UINT32 ulTime)
- {
- return CAST_TO_INT64 (m_ulTSRollOver) * CAST_TO_INT64 MAX_UINT32 + CAST_TO_INT64 ulTime;
- }
- INT64 HXBufferingState::CreateINT64Timesync(UINT32 ulTime)
- {
- return CAST_TO_INT64 (m_ulTimeSyncRollOver) * CAST_TO_INT64 MAX_UINT32 + CAST_TO_INT64 ulTime;
- }
- void HXBufferingState::OnPacket(UINT32 ulTimestamp, UINT32 ulPacketSize,
- UINT32 ulElapsedTime,
- BOOL bIsLive, BOOL bIsBufferedPlayMode)
- {
- // 0xFA .. 0xFF [roll over] (0x01)
- if (m_ulLastPacketTimeStamp > ulTimestamp &&
- ((m_ulLastPacketTimeStamp - ulTimestamp) > MAX_TIMESTAMP_GAP))
- {
- m_ulTSRollOver++;
- }
-
- INT64 llActualTimeStamp = CreateINT64Timestamp(ulTimestamp);
- m_ulLastPacketTimeStamp = ulTimestamp;
- if (m_bIsFirstPacket)
- {
- /* Only if we are live, store the first packet timestemp
- * as the lowest timestamp. In any other case, we consider
- * the lowest ts to be 0 OR the Seek time.
- * This is to fix the post-seek buffering where we should not
- * account any packets < seek ts towards buffering completion.
- */
- if (bIsLive)
- {
- m_llLowestTimeStamp = CAST_TO_INT64 ulTimestamp;
- m_llFirstLivePacketTimestamp = m_llLowestTimeStamp;
- }
- m_llHighestTimeStamp = CAST_TO_INT64 ulTimestamp;
- m_bIsFirstPacket = FALSE;
- }
- // Add this packet to our packet info statistics
- AddPktInfo(llActualTimeStamp, ulPacketSize);
- // data based preroll
- if (DataBasedPreroll())
- {
- m_ulCurrentBuffering += ulPacketSize;
-
- if (bIsBufferedPlayMode)
- {
- /*
- * We wait to have at least 1 second worth of data
- * before doing any calculations. This may need some
- * tweaking.
- */
- if ((m_ulRemainingToBuffer != 0) &&
- (m_ulCurrentBuffering >= m_ulAvgBandwidth / 8))
- {
- /*
- * Highly unlikely, but may happen from a server on the
- * local machine.
- */
- if (ulElapsedTime == 0)
- {
- if (m_ulCurrentBuffering >= m_ulMinimumPreroll)
- {
- m_ulRemainingToBuffer = 0;
- }
- }
- else
- {
- UINT32 ulDenom = ulElapsedTime * m_ulAvgBandwidth / 8000;
-
- /* Sanity check - may be 0 only when bandwidth
- * is really low
- */
- ulDenom = ulDenom > 0 ? ulDenom : 1;
-
- CalcRemainingToBuffer(ulDenom);
- }
- }
- }
- else
- {
- /* bIsBufferedPlayMode == FALSE */
- if (m_ulRemainingToBuffer)
- {
- CalcRemainingToBuffer();
- }
- }
- }
- if (llActualTimeStamp >= m_llHighestTimeStamp)
- {
- m_llHighestTimeStamp = llActualTimeStamp;
- }
- }
- void HXBufferingState::UpdateBufferingInMs(INT64 llRefLowTimestamp,
- INT64 llHighTimestamp,
- BOOL bIsBufferedPlayMode,
- BOOL bIsTimestampDelivery,
- UINT32 ulElapsedTime)
- {
- UpdateCurrentBufferingInMs(llRefLowTimestamp, llHighTimestamp);
- if (bIsBufferedPlayMode)
- {
- /* We handle time stamp delivered streams differently
- * in case of BUffered/PerfectPlay. This is because
- * server sends timestamp delivered stream based
- * on the timestamps on the packet and pretty
- * much streams in realtime.
- * So even if we are on LAN and streaming a RealText
- * file, we will get packets in realtime even though
- * we have enough bandwidth available
- *
- * For timestamp delivered streams, we just fulfill
- * preroll.
- */
- if (bIsTimestampDelivery &&
- m_ulCurrentBufferingInMs > m_ulMinimumPrerollInMs)
- {
- m_ulRemainingToBufferInMs = 0;
- }
- else if ((m_ulRemainingToBufferInMs != 0) &&
- (m_ulCurrentBufferingInMs >= 1000))
- {
- /*
- * Highly unlikely, but may happen from a
- * 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;
- }