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

📄 fbbufctl.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* ***** 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 "hxcom.h"
#include "fbbufctl.h"
#include "hlxclib/math.h"
#include "hxprefutil.h"

//#define HELIX_FEATURE_DBG_LOG
//#define BUFFER_CONTROL_TESTING

#include "hxtick.h"
#include "errdbg.h"
#include "hxstring.h"
#include "hxurl.h"
#include "ihxpckts.h" // IHXValues
#include "hxfiles.h" // IHXRequest

HXFeedbackControl::HXFeedbackControl() :
    m_delt(0),
    m_a1(0),
    m_a2(0),
    m_b1(0),
    m_b2(0),
    m_ulSetPoint(0),
    m_ulMin(0),
    m_ulMax(0xffffffff),
    m_e1(0),
    m_e2(0),
    m_c1(0),
    m_c2(0)
{}

void HXFeedbackControl::Init(double c, double wn, double Kv, double delt)
{
    // calculate coefficients
    double d = exp(-wn * c);
    double wd = wn * sqrt(1.0 - c *c);
    double pReal = d * cos(wd);
    double pImag = d * sin(wd);

    m_b1 = -2.0 * pReal;
    m_b2 = pReal * pReal + pImag * pImag;
    m_a1 = 2.0 + m_b1 - (1.0 + m_b1 + m_b2)/(Kv * delt);
    m_a2 = 1.0 + m_b1 + m_b2 - m_a1;

    m_delt = delt;
}
    
void HXFeedbackControl::Reset(UINT32 ulSetPoint, 
                              INT32 e1, INT32 e2,
                              UINT32 c1, UINT32 c2)
{
    m_ulSetPoint = ulSetPoint;
    m_e1 = e1;
    m_e2 = e2;
    m_c1 = c1;
    m_c2 = c2;
}

void HXFeedbackControl::SetLimits(UINT32 ulMin, UINT32 ulMax)
{
    m_ulMin = ulMin;
    m_ulMax = ulMax;
}

UINT32 HXFeedbackControl::Control(UINT32 ulCurrentBits)
{
    INT32 error =  (INT32)m_ulSetPoint - (INT32)ulCurrentBits;
    UINT32 ulControlBw = 0;
    
    double u1 = (m_a1 * (double)error + 
                 (m_a2 - m_a1) * (double)m_e1 -
                 m_a2 * (double)m_e2) / m_delt;
    
    double u2 = -((m_b1 - m_a1) * (double)m_c1 +
                  (m_b2 - m_a2) * (double)m_c2);
    
    ulControlBw = RoundAndClip(u1 + u2);

    Enqueue(error, ulControlBw);

    return ulControlBw;
}

UINT32 HXFeedbackControl::RoundAndClip(double value) const
{
    UINT32 ulRet = m_ulMin;

    if (value > m_ulMax)
    {
        // Saturate to max
        ulRet = m_ulMax;
    }
    else if (value > m_ulMin)
    {
        // Value within range.
        // Round to nearest integer
        ulRet = (UINT32)(value + 0.5);
    }

    return ulRet;
}

void HXFeedbackControl::Enqueue(INT32 error, UINT32 ulBandwidth)
{
    m_e2 = m_e1;
    m_e1 = error;

    m_c2 = m_c1;
    m_c1 = ulBandwidth;
}

HXFeedbackBufferControl::HXFeedbackBufferControl() :
    m_lRefCount(0),
    m_pScheduler(NULL),
    m_callbackHandle(0),
    m_pSource(NULL),
    m_pBufferStats(NULL),
    m_pThin(NULL),
    m_pPrefs(NULL),
    m_pStatus(NULL),
    m_pErrMsg(NULL),
    m_ulClipBw(0),
    m_nControlStream(0),
    m_ulControlBw(0),
    m_bControlTotal(FALSE),
    m_bPaused(TRUE),
    m_state(csNotInitialized)
{
    m_control.Init(0.7, 1.25664, 0.2, 5.0);
}

HXFeedbackBufferControl::~HXFeedbackBufferControl()
{
    Close();
}

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

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

STDMETHODIMP_(ULONG32) HXFeedbackBufferControl::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 HXFeedbackBufferControl::Init(THIS_ IUnknown* pContext)
{
    HX_RESULT res = HXR_FAILED;
    
    Close();

    if (pContext)
    {
        pContext->QueryInterface(IID_IHXErrorMessages, (void**)&m_pErrMsg);

        if ((HXR_OK == pContext->QueryInterface(IID_IHXScheduler, 
                                                (void**)&m_pScheduler)) &&
            (HXR_OK == pContext->QueryInterface(IID_IHXStreamSource, 
                                                (void**)&m_pSource)) &&
            (m_pSource) && 
            (HXR_OK == m_pSource->QueryInterface(IID_IHXThinnableSource, 
                                                 (void**)&m_pThin)) &&
            (HXR_OK == pContext->QueryInterface(IID_IHXSourceBufferingStats2,
                                                (void**)&m_pBufferStats)) &&
            (HXR_OK == pContext->QueryInterface(IID_IHXPendingStatus, 
                                                (void**)&m_pStatus)) &&
            (HXR_OK == pContext->QueryInterface(IID_IHXPreferences, 
                                                (void**)&m_pPrefs)) &&
            (HXR_OK == ReadPrefSettings()))

        {
#ifdef BUFFER_CONTROL_TESTING
            res = InitTesting(pContext);
#endif
            res = HXR_OK;
        }
        else
        {
            ChangeState(csError);
        }
    }
    return res;
}

/************************************************************************
 *      Method:
 *          IHXBufferControl::OnBuffering
 *      Purpose:
 *          Called while buffering
 */
STDMETHODIMP HXFeedbackBufferControl::OnBuffering(UINT32 ulRemainingInMs,
                                                  UINT32 ulRemainingInBytes)
{
    DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL,(s, "FBBC::OnBuffering(%d, %d)",
                                             ulRemainingInMs, ulRemainingInBytes));
    
    if (Initialized() &&
        (csBuffering != m_state))
    {
        ChangeState(csBuffering);

        SetBandwidth(m_ulClipBw);
    }
    
    return HXR_OK;
}

/************************************************************************
 *      Method:
 *          IHXBufferControl::OnBufferingDone
 *      Purpose:
 *      Called when buffering is done
 */
STDMETHODIMP HXFeedbackBufferControl::OnBufferingDone(THIS)
{
    DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL,(s, "FBBC::OnBufferingDone"));

    if (Initialized())
    {
        HX_ASSERT(csBuffering == m_state);

        UINT32 ulTotalBits = 0;
        UINT32 ulControlBits = 0;

        GetControlData(ulTotalBits, ulControlBits);

        DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL,
                  (s, "FBBC::OnBufferingDone() %d %d",
                   ulTotalBits,
                   ulControlBits));

        UINT32 ulSetPoint = ulControlBits;

        if (ulSetPoint < m_control.SetPoint())
        {
            // If the new setpoint is less than a 
            // previous value, ignore it and use
            // the old setpoint.
            ulSetPoint = m_control.SetPoint();
        }

        DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL, 
                  (s, "FBBC::OBD reset control %lu",
                   ulSetPoint));

        m_control.Reset(ulSetPoint,
                        0, 0,                          // Error state
                        m_ulControlBw, m_ulControlBw); // control state

        if (m_bPaused)
        {
            ChangeState(csPaused);
        }
        else
        {
            ChangeState(csPlaying);
        }
    }

    return HXR_OK;
}

/************************************************************************
 *      Method:
 *          IHXBufferControl::OnResume
 *      Purpose:
 *          Called when playback is resumed
 */
STDMETHODIMP HXFeedbackBufferControl::OnResume()
{
    DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL,(s, "FBBC::OnResume"));

    m_bPaused = FALSE;

    if (csError != m_state)
    {
        if (HXR_OK == GetBwInfo(m_ulClipBw, m_nControlStream, m_ulControlBw))
        {
            DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL,
                      (s, "FBBC::OnResume : clipBw %lu ctlStr %u ctlBw %lu", 
                       m_ulClipBw,
                       m_nControlStream,
                       m_ulControlBw));
            

            SetTransportByteLimits(m_ulClipBw);

            if (m_pSource && !m_pSource->IsLive() && 
                m_ulClipBw && m_ulControlBw)
            {
                /* Only activate the algorithm for on-demand clips that
                 * have bitrate information
                 */
                if (csNotInitialized == m_state)
                {
                    StartCallback();
                }
            
                ChangeState(csPlaying);
            }

            SetBandwidth(m_ulClipBw);
        }
    }

    return HXR_OK;
}
    
/************************************************************************
 *      Method:
 *          IHXBufferControl::OnPause
 *      Purpose:
 *          Called when playback is paused
 */
STDMETHODIMP HXFeedbackBufferControl::OnPause()
{
    DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL, (s, "FBBC::OnPause"));
    
    m_bPaused = TRUE;

    if (Initialized())
    {
        ChangeState(csPaused);
    }

    return HXR_OK;
}

/************************************************************************
 *      Method:
 *          IHXBufferControl::OnSeek
 *      Purpose:
 *          Called when a seek occurs
 */
STDMETHODIMP HXFeedbackBufferControl::OnSeek(THIS)
{
    DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL, (s, "FBBC::OnSeek"));

    if (Initialized())
    {
        ChangeState(csSeeking);
    }

    return HXR_OK;
}

/************************************************************************
 *      Method:
 *          IHXBufferControl::OnClipEnd
 *      Purpose:
 *          Called when we get the last packet in the clip
 */
STDMETHODIMP HXFeedbackBufferControl::OnClipEnd(THIS)
{
    DEBUG_OUT(m_pErrMsg, DOL_BUFFER_CONTROL, (s, "FBBC::OnClipEnd"));

    if (Initialized())
    {
        ChangeState(csClipEnd);
    }

    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 HXFeedbackBufferControl::Close(THIS)
{
    HX_RELEASE(m_pErrMsg);

    StopCallback();
    HX_RELEASE(m_pScheduler);

    HX_RELEASE(m_pBufferStats);
    HX_RELEASE(m_pSource);
    HX_RELEASE(m_pThin);
    HX_RELEASE(m_pPrefs);
    HX_RELEASE(m_pStatus);

    ChangeState(csNotInitialized);

    return HXR_OK;
}

⌨️ 快捷键说明

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