⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buffmgr.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	!(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 + -