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

📄 buffmgr.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* ***** BEGIN LICENSE BLOCK ***** 
 * Version: RCSL 1.0/RPSL 1.0 
 *  
 * Portions Copyright (c) 1995-2002 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 "hlxclib/stdio.h"

#include "hxcom.h"
#include "hxcomm.h"
#include "ihxpckts.h"
#include "hxslist.h"
#include "hxtick.h"
#include "hxcore.h"
#include "chxeven.h"
#include "hxbsrc.h"
#include "hxsrc.h"
#include "hxntsrc.h"
#include "hxstrm.h"
#include "strminfo.h"
#include "buffmgr.h"
#include "hxsmbw.h"

#include "hxgroup.h"
#include "hxplay.h"
#include "errdbg.h"

#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif

#if defined(__TCS__)
#define MAX_ADDITIONAL_BUFFERING    3000
#else
#define MAX_ADDITIONAL_BUFFERING    10000
#endif /* __TCS__ */

CBufferManager::CBufferManager(HXSource* pParent)
{
    m_ulMaxAdditionalBufferingInMs  = MAX_ADDITIONAL_BUFFERING;

    m_llHighestTimeStamp	= 0;
    m_ulTotalPauseTime		= 0;
    m_ulLastPauseTime		= 0;
    m_ulAdditionalBufferingInMs	= 0;
    m_bBufferStartTimeToBeSet	= TRUE;

    m_ulMinimumInitialAudioPreroll	= 0;
    m_ulMinimumSourcePreroll	= 0;

    m_bPerfectPlay		= FALSE;     
    m_bPaused			= FALSE;
    m_state			= BUFFMGR_READY;

    m_pParent			= pParent;
    m_pParent->AddRef();

    m_bLocalPlayback		= pParent->IsLocalSource();
    m_pStreamInfoTable		= pParent->GetStreamInfoTable();
    m_bFirstResumeDone		= FALSE;
    m_bIsSeekPerformed		= FALSE;
    m_bBufferedPlay		= FALSE;
    m_bBufferCalcToBeChanged	= FALSE;
    m_bIsInitialized		= FALSE;
    m_ulSeekTime		= 0;
}

CBufferManager::~CBufferManager()
{
    HX_RELEASE(m_pParent);
}

HX_RESULT
CBufferManager::Init()
{
    UINT32	    ulPerfectPlayTime = 0;
    UINT32	    ulMinimumPreroll = 0;
    STREAM_INFO*    pStreamInfo = NULL;

    CHXMapLongToObj::Iterator i;

    // There is no buffered or perfect play with MIN_HEAP on.
#if !defined(HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
    SetPerfectPlay(m_pParent->IsPerfectPlay());

    if (m_bPerfectPlay || m_bBufferedPlay)
    {
	// caculate how much extra preroll for the perfect play
	ulPerfectPlayTime = m_pParent->GetPerfectPlayTime();
    }
#endif

    // ajust buffering information of each stream
    for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
    {
	pStreamInfo = (STREAM_INFO*) (*i);

	pStreamInfo->BufferingState().Init(ulPerfectPlayTime);

	HX_ASSERT(pStreamInfo->m_EventList.GetHeadPosition() == NULL);
    }

    m_bIsInitialized = TRUE;

    /* Was there a Seek called before Initialization... may happen for a clip
     * with Start time
     */
    if (m_bIsSeekPerformed)
    {
	DoSeek(m_ulSeekTime);
    }

    return HXR_OK;
}

HX_RESULT
CBufferManager::SetMinimumPreroll(BOOL bPerfectPlay, UINT32 ulSourcePreroll, 
				  UINT32 ulInitialAudioPreroll,
				  BOOL	 bModifyStartTime /* = TRUE */)
{
    m_ulMinimumInitialAudioPreroll = ulInitialAudioPreroll;
    m_ulMinimumSourcePreroll	   = ulSourcePreroll;

    SetPerfectPlay(bPerfectPlay);

    UpdateMinimumPreroll(bModifyStartTime);

    return HXR_OK;
}

void 
CBufferManager::UpdateMinimumPreroll(BOOL bModifyStartTime)
{
    UINT32	    ulMinimumPreroll = 0;
    UINT32	    ulPerfectPlayTime = 0;
    UINT32	    ulStartTime = 0;
    UINT32	    ulEventStartTime = 0;
    UINT32	    ulPacketTime     = 0;
    STREAM_INFO*    pStreamInfo = NULL;
    BOOL	    bPreDataToBeCalculated = FALSE;

    CHXMapLongToObj::Iterator i;

    // There is no buffered or perfect play with MIN_HEAP on.
#if !defined(HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)

    if (m_bPerfectPlay || m_bBufferedPlay)
    {
	m_ulMaxAdditionalBufferingInMs = 0;
	// caculate how much extra preroll for the perfect play
	ulPerfectPlayTime = m_pParent->GetPerfectPlayTime();
    }
    else
    {
	m_ulMaxAdditionalBufferingInMs	= MAX_ADDITIONAL_BUFFERING;

	if (m_ulAdditionalBufferingInMs > m_ulMaxAdditionalBufferingInMs)
	{
	    m_ulAdditionalBufferingInMs = m_ulMaxAdditionalBufferingInMs;
	}

	ulPerfectPlayTime		= m_ulAdditionalBufferingInMs;
    }
#endif

    ulStartTime = m_pParent->GetStartTime();

    // adjust buffering information of each stream
    for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
    {
	pStreamInfo = (STREAM_INFO*) (*i);
    
	pStreamInfo->BufferingState().SetMinimumPreroll(
	    m_ulMinimumSourcePreroll, 
	    m_ulMinimumInitialAudioPreroll,
	    ulPerfectPlayTime,
	    (m_state == BUFFMGR_REBUFFER));

	if (bModifyStartTime)
	{
	    pStreamInfo->UpdateStartTimes(ulStartTime);
	}
    }

    m_bBufferCalcToBeChanged = FALSE;
}

HX_RESULT
CBufferManager::Stop(void)
{
    STREAM_INFO*    pStreamInfo = NULL;

    CHXMapLongToObj::Iterator i;

    // stop buffering of each stream
    for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
    {
	pStreamInfo = (STREAM_INFO*) (*i);
    
	pStreamInfo->BufferingState().Stop();
//	DEBUG_OUT(m_pParent->m_pPlayer, (s,
//	    "BufferManager::Stop %p", pStreamInfo));
    }

    return HXR_OK;
}

HX_RESULT
CBufferManager::DoSeek(UINT32 ulSeekTime, BOOL bSeekInsideRecordBuffer)
{
    m_state		= BUFFMGR_SEEK;
    m_bIsSeekPerformed	= TRUE;
    m_ulSeekTime	= ulSeekTime;

    /* We will call Reset during Init() call */
    if (!m_bIsInitialized)
    {
	return HXR_OK;
    }

    // reset all the preroll attributes
    Reset(ulSeekTime, bSeekInsideRecordBuffer);

    return HXR_OK;
}

HX_RESULT
CBufferManager::DoPause(void)
{
    m_bPaused		= TRUE;
    m_ulLastPauseTime	= HX_GET_TICKCOUNT();
    return HXR_OK;
}

HX_RESULT
CBufferManager::DoResume(void)
{
    if (m_bPaused && m_state != BUFFMGR_SEEK && !m_bBufferStartTimeToBeSet)
    {
	m_ulTotalPauseTime += CALCULATE_ELAPSED_TICKS(m_ulLastPauseTime, HX_GET_TICKCOUNT());
    }

    m_bPaused = FALSE;

    if (!m_bFirstResumeDone)
    {
	m_bFirstResumeDone = TRUE;

	UpdateMinimumPreroll(FALSE);
    }

    return HXR_OK;
}

HX_RESULT
CBufferManager::ReBuffer(void)
{
    // recaculate only if it is out of the buffering stage
    // and not in perfect play mode
    m_state = BUFFMGR_REBUFFER;
    
    /* go back in buffering mode...
     * each time we come in buffering state, increase the
     * number of packets we buffer by 1 second worth
     * to a max of m_ulMaxAdditionalBuffering secs.
     */
#ifndef HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES
    // increase by 1 sec
    m_ulAdditionalBufferingInMs += 1000;

    if (m_pParent->IsLive())
    {
	m_bPerfectPlay	= FALSE;
	m_bBufferedPlay = FALSE;
    }
#endif // HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES

    UpdateMinimumPreroll(FALSE);

    return HXR_OK;
}

HX_RESULT
CBufferManager::Reset(UINT32 ulSeekTime, BOOL bSeekInsideRecordBuffer)
{
    STREAM_INFO*    pStreamInfo = NULL;

    CHXEventList*  pEventList = NULL;
    CHXEvent*	    pEvent = NULL;

    CHXMapLongToObj::Iterator i;

    if (m_bBufferCalcToBeChanged)
    {
	UpdateMinimumPreroll(FALSE);
    }

    m_ulBufferingStartTime = 0;

    // reset each stream
    for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
    {
	pStreamInfo = (STREAM_INFO*) (*i);
	
	// reset
	if (!bSeekInsideRecordBuffer)
	{
	    pStreamInfo->m_bSrcStreamDone = FALSE;
	    pStreamInfo->m_bPacketRequested = FALSE;
	}

	pStreamInfo->m_bSrcStreamFillingDone = FALSE;

	// Reset buffering state
	pStreamInfo->BufferingState().Reset((m_state == BUFFMGR_SEEK),
					    ulSeekTime);

	

	HX_ASSERT(m_state == BUFFMGR_SEEK);

	if (m_state == BUFFMGR_SEEK)
	{
	    // remove all pending packets 
	    pEventList = &pStreamInfo->m_EventList;
	    while (pEventList->GetNumEvents() > 0)
	    {
		pEvent = pEventList->RemoveHead();

		// Mark it as a pre-seek event and send it to the player
		pEvent->SetPreSeekEvent();
		m_pParent->EventReady(pEvent);
	    }
	}
    }

    m_llHighestTimeStamp	= 0;
    m_ulTotalPauseTime		= 0;
    m_bBufferStartTimeToBeSet	= TRUE;
    return HXR_OK;
}
					
HX_RESULT
CBufferManager::UpdateCounters(IHXPacket* pPacket)
{
    HX_RESULT	    hr = HXR_OK;
    UINT32	    ulStreamNum = 0;
    UINT32	    ulBufferSize = 0;
    UINT32	    ulBufferTime = 0;
    UINT32	    ulElapsedTime = 0;
    INT64	    llActualTimeStamp = 0;
    IHXBuffer*	    pBuffer = NULL;
    STREAM_INFO*    pStreamInfo = NULL;
    STREAM_INFO*    pThisStreamInfo = NULL;
    UINT32	    ulCurrentTime   = HX_GET_TICKCOUNT();


    CHXMapLongToObj::Iterator i;
   
    if (!pPacket)
    {
	return HXR_INVALID_PARAMETER;
    }

    if (pPacket->IsLost() &&

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -