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

📄 wmbufctl.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
字号:
/* ***** 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 "hxtypes.h"
#include "hxresult.h"
#include "hxcom.h"

#include "wmbufctl.h"

#include "hxstring.h"
#include "hxbsrc.h" // HXSource

#include "hxtick.h"
#include "debug.h"
#define D_WM_BUF_CTL 0x10000000

/* Added these constants temporarily to tell ASM when to slow down
 * Accelerated buffering
 */
#define MAX_BUFFERING_INMS              20000
#define MAX_BUFFERING_INBYTES           4000000

/*
 * These constants are to tell ASM to slow down below the stated clip rate
 * if we have buffered an insane amount of data.
 * This can happen if the bitrate of a stream is signficantly lower at some
 * points then the actual clip rate (i.e. high bit-rate video).  These values
 * need to be VERY aggressive so we don't cut off things like flash which
 * will get WAY ahead and then spend the bits later on in the clip.
 */
#define MAX_BUFFERING_SLOW_HALF_INMS            300000
#define MAX_BUFFERING_SLOW_HALF_INBYTES         5000000

#define MAX_BUFFERING_SLOW_ONE_HUNDRETH_INMS    400000
#define MAX_BUFFERING_SLOW_ONE_HUNDRETH_INBYTES 6000000


HXWatermarkBufferControl::HXWatermarkBufferControl() :
    m_lRefCount(0),
    m_pSource(NULL),
    m_ChillState(HX_NONE)
{
    DPRINTF(D_WM_BUF_CTL, ("HXWatermarkBufferControl()\n"));
}
    
HXWatermarkBufferControl::~HXWatermarkBufferControl()
{
    HX_RELEASE(m_pSource);
}

/*
 *	IUnknown methods
 */
STDMETHODIMP HXWatermarkBufferControl::QueryInterface(THIS_
						      REFIID riid,
						      void** ppvObj)
{
    QInterfaceList qiList[] =
    {
	{ GET_IIDHANDLE(IID_IUnknown), (IUnknown*)this }, 
	{ GET_IIDHANDLE(IID_IHXBufferControl), (IHXBufferControl*)this },
	{ GET_IIDHANDLE(IID_IHXWatermarkBufferControl), (IHXWatermarkBufferControl*)this }
    };
    
    return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
}

STDMETHODIMP_(ULONG32) HXWatermarkBufferControl::AddRef(THIS)
{
    return InterlockedIncrement(&m_lRefCount);
}

STDMETHODIMP_(ULONG32) HXWatermarkBufferControl::Release(THIS)
{
    if (InterlockedDecrement(&m_lRefCount) > 0)
    {
	return m_lRefCount;
    }

    delete this;
    return 0;
}

/*
 * IHXBufferControl method
 */

/************************************************************************
 *	Method:
 *	    IHXBufferControl::Init
 *	Purpose:
 *          Initialize the buffer control object with a context
 *          so it can find the interfaces it needs to do buffer
 *          control
 */
STDMETHODIMP HXWatermarkBufferControl::Init(THIS_ IUnknown* pContext)
{
    return HXR_OK;
}

/************************************************************************
 *	Method:
 *	    IHXBufferControl::OnBuffering
 *	Purpose:
 *          Called while buffering
 */
STDMETHODIMP HXWatermarkBufferControl::OnBuffering(UINT32 ulRemainingInMs,
						   UINT32 ulRemainingInBytes)
{
    return ResetAccelState();
}


/************************************************************************
 *	Method:
 *	    IHXBufferControl::OnBufferingDone
 *	Purpose:
 *      Called when buffering is done
 */
STDMETHODIMP HXWatermarkBufferControl::OnBufferingDone(THIS)
{
    return HXR_OK;
}


/************************************************************************
 *	Method:
 *	    IHXBufferControl::OnResume
 *	Purpose:
 *          Called when playback is resumed
 */
STDMETHODIMP HXWatermarkBufferControl::OnResume(THIS)
{
    return ResetAccelState();
}
    
/************************************************************************
 *	Method:
 *	    IHXBufferControl::OnPause
 *	Purpose:
 *          Called when playback is paused
 */
STDMETHODIMP HXWatermarkBufferControl::OnPause(THIS)
{
    return HXR_OK;
}

/************************************************************************
 *	Method:
 *	    IHXBufferControl::OnSeek
 *	Purpose:
 *          Called when a seek occurs
 */
STDMETHODIMP HXWatermarkBufferControl::OnSeek(THIS)
{
    return ResetAccelState();
}

/************************************************************************
 *	Method:
 *	    IHXBufferControl::OnClipEnd
 *	Purpose:
 *          Called when we get the last packet in the clip
 */
STDMETHODIMP HXWatermarkBufferControl::OnClipEnd(THIS)
{
    return HXR_OK;
}

/************************************************************************
 *	Method:
 *	    IHXBufferControl::Close()
 *	Purpose:
 *          Called when the owner of this object wishes to shutdown
 *          and destroy this object. This call causes the buffer control
 *          object to release all it's interfaces references.
 */
STDMETHODIMP HXWatermarkBufferControl::Close(THIS)
{
    ClearChillState();

    HX_RELEASE(m_pSource);

    return HXR_OK;
}

/*
 * IHXWatermarkBufferControl method
 */

/************************************************************************
 *	Method:
 *	    IHXWatermarkBufferControl::SetSource
 *	Purpose:
 *          Tells the object what HXSource object it is associated with.
 */
STDMETHODIMP HXWatermarkBufferControl::SetSource(THIS_ HXSource* pSource)
{
    HX_RESULT res = HXR_FAILED;

    HX_RELEASE(m_pSource);
    m_pSource = pSource;

    if( m_pSource)
    {
	m_pSource->AddRef();
	res = HXR_OK;
    }

    return res;
}

/************************************************************************
 *	Method:
 *	    IHXWatermarkBufferControl::OnBufferReport
 *	Purpose:
 *          Initiates control operations based on buffering information.
 *      
 */
STDMETHODIMP HXWatermarkBufferControl::OnBufferReport(THIS_ 
						      UINT32 ulBufferInMs,
						      UINT32 ulBuffer)
{
    DPRINTF(D_WM_BUF_CTL, ("WBC::OBR %u %u %u %u %s\n",
			   HX_GET_TICKCOUNT(),
			   ulBufferInMs,
			   ulBuffer,
			   m_ChillState,
			   (m_ChillState == HX_NONE) ? "NONE" :
			   (m_ChillState == CHILL) ? "CHILL" :
			   (m_ChillState == HALF) ? "HALF" :
			   (m_ChillState == HUNDRETH) ? "HUNDRETH" :
			   "UNKNOWN"));

    if (m_ChillState == HALF && 
	(ulBufferInMs > MAX_BUFFERING_SLOW_ONE_HUNDRETH_INMS ||
	 ulBuffer > MAX_BUFFERING_SLOW_ONE_HUNDRETH_INBYTES))
    {
	m_ChillState = HUNDRETH;
	ChangeAccelerationStatus(FALSE, TRUE, 1);
    }
    else if (m_ChillState == CHILL && 
	     (ulBufferInMs > MAX_BUFFERING_SLOW_HALF_INMS ||
	      ulBuffer > MAX_BUFFERING_SLOW_HALF_INBYTES))
    {
	m_ChillState = HALF;
	ChangeAccelerationStatus(FALSE, TRUE, 50);
    }
    /*
     * XXXSMP  Perhaps we want to stop at MAX_BUFFERING on the way back
     * to MAX_BUFFERING / 2 (In the case where we are at HALF or HUNDRETH.
     * This will prevent switch to CHILL and then HALF again on the way
     * back down.  No big deal for now.
     */
    else if (m_ChillState == HX_NONE &&
	     (ulBufferInMs > MAX_BUFFERING_INMS ||
	      ulBuffer > MAX_BUFFERING_INBYTES))
    {
	m_ChillState = CHILL;
	ChangeAccelerationStatus(FALSE, FALSE, 0);
    }
    else if (m_ChillState != HX_NONE &&
	     (ulBufferInMs < MAX_BUFFERING_INMS/2 &&
	      ulBuffer < MAX_BUFFERING_INBYTES/2))
    {
	m_ChillState = HX_NONE;
	ChangeAccelerationStatus(TRUE, FALSE, 0);
    }

    return HXR_OK;
}

/************************************************************************
 *	Method:
 *	    IHXWatermarkBufferControl::ClearChillState
 *	Purpose:
 *          Sets the chill state to NONE
 *      
 */
STDMETHODIMP HXWatermarkBufferControl::ClearChillState(THIS)
{
    m_ChillState = HX_NONE;

    return HXR_OK;
}


HX_RESULT
HXWatermarkBufferControl::ChangeAccelerationStatus(BOOL bMayBeAccelerated,
						   BOOL bUseAccelerationFactor,
						   UINT32 ulAccelerationFactor)
{
    IHXBandwidthManager* pMgr = 0;
    
    HX_RESULT res = m_pSource->QueryInterface(IID_IHXBandwidthManager, 
					      (void **)&pMgr);
    if (pMgr)
    {
	pMgr->ChangeAccelerationStatus(m_pSource, bMayBeAccelerated,
				       bUseAccelerationFactor, 
				       ulAccelerationFactor);
	pMgr->Release();
    }

    return res;
}

HX_RESULT HXWatermarkBufferControl::ResetAccelState()
{
    if (m_ChillState != HX_NONE)
    {
	m_ChillState = HX_NONE;
	ChangeAccelerationStatus(TRUE, FALSE, 0);
    }

    return HXR_OK;
}

⌨️ 快捷键说明

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