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

📄 hxsmstr.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"      /* printf */
#include "hlxclib/stdlib.h"     /* atoi on Mac */
#include "hxtypes.h"    /* Basic Types */
#include "hxcom.h"      /* IUnknown */ 
#include "hxcore.h"    /* IHXStream */
#include "hxerror.h"
#include "hxasm.h"
#include "hxsmbw.h"
#include "hxmap.h"
#include "hxcomm.h"
#include "hxengin.h"
#include "hxsmstr.h"	/* HXASMStream */
#include "hxsmutil.h"
#include "ihxpckts.h"
#include "hxprefs.h"
#include "hxstrm.h"
#include "hxcore.h"
#include "asmrulep.h"
#include "hxmon.h"
#include "chxpckts.h"
#include "hxassert.h"
#include "hxslist.h"
#include "hxbsrc.h"
#include "hxsrc.h"
#include "hxstrutl.h"
#include "errdbg.h"
#include "rtspif.h"
#include "rlstate.h"
#include "hxmime.h"

#include "hxheap.h"

#ifdef _DEBUG
#undef HX_THIS_FILE		
static const char HX_THIS_FILE[] = __FILE__;
#endif

HXASMStream::HXASMStream(HXStream* pStream, HXSource* pSource)
    : m_lRefCount(0)
    , m_pRuleBook(0)
    , m_pLossCB(0)
    , m_ulLossCBHandle(0)
    , m_pSubInfo(0)
    , m_ulRuleBw(0)
    , m_ulRulePreData(0)
    , m_ulCurrentPreData(0)
    , m_ulCurrentBandwidth(0)
    , m_bRuleTimeStampDelivery(0)
    , m_ulSubscribedBw(0)
    , m_lBias(0)
    , m_ulFixedBandwidth(0)
    , m_ulBandwidthAllocation(0)
    , m_bStartRecalc(FALSE)
    , m_bTimeStampDeliveryMode(FALSE)
    , m_ulLastLimitBandwidth(0xffffffff)
    , m_pAtomicRuleChange(0)
    , m_pSubList(0)
    , m_pSubscriptionVariables(0)
    , m_nNumRules(0)    
    , m_pRuleSubscribeStatus(NULL)
    , m_pASMRuleState(NULL)
    , m_bHasExpression(FALSE)
    , m_bEndOneRuleEndAll(FALSE)
    , m_ulLastBandwidth(0)
#ifndef GOLD
    , m_pEM(0)
#endif
{
    m_pStreamSinkMap = new CHXMapPtrToPtr;
    
    UINT32  ulStreamID;
    IHXPlayer* pPlayer;
    IHXPreferences* pPreferences=NULL;    

    pStream->GetID(ulStreamID);
    m_pSource = pSource;
    m_pSource->AddRef();
    m_pHeader = pStream->GetHeader();
    m_uStreamNumber = pStream->GetStreamNumber();

    /* Hold onto some useful interfaces */

    m_pSource->GetPlayer(pPlayer);
    pPlayer->QueryInterface(IID_IHXRegistry,  (void **)&m_pRegistry);
    pPlayer->QueryInterface(IID_IHXScheduler,   (void **)&m_pScheduler);
    pPlayer->Release();

    /*
     * WARNING!  You must update all interfaces queried off the source
     * in ResetASMSource().
     */
    m_pSource->QueryInterface(IID_IHXASMSource, (void **)&m_pASMSource);
    m_pSource->QueryInterface(IID_IHXAtomicRuleChange,
	(void **)&m_pAtomicRuleChange);

#ifndef GOLD
    pPlayer->QueryInterface(IID_IHXErrorMessages, (void **)&m_pEM);
#endif

    UINT32 ulEndOneruleEndAll = 0;
    if (m_pHeader->GetPropertyULONG32("EndOneRuleEndAll", ulEndOneruleEndAll) == HXR_OK)
    {
	m_bEndOneRuleEndAll = (ulEndOneruleEndAll == 1);
    }
    /* temporary hack to properly shut down RA and RV streams with end time */
    else
    {	
	IHXBuffer* pMimeType = NULL;
	m_pHeader->GetPropertyCString("MimeType", pMimeType);

	if (pMimeType && 
	    ((::strcasecmp((const char*) pMimeType->GetBuffer(), REALAUDIO_MIME_TYPE) == 0) ||
	     (::strcasecmp((const char*) pMimeType->GetBuffer(), REALAUDIO_MULTIRATE_MIME_TYPE) == 0) ||
	     (::strcasecmp((const char*) pMimeType->GetBuffer(), REALVIDEO_MIME_TYPE) == 0) ||
	     (::strcasecmp((const char*) pMimeType->GetBuffer(), REALVIDEO_MULTIRATE_MIME_TYPE) == 0)))
	{
	    m_bEndOneRuleEndAll = TRUE;
	}

	HX_RELEASE(pMimeType);
    }

    /* Extract RuleBook from the stream header */

    IHXBuffer* pRuleBook = NULL;
    m_pHeader->GetPropertyCString("ASMRuleBook", pRuleBook);
    if (pRuleBook)
    {
        m_pRuleBook = new ASMRuleBook ((const char *)pRuleBook->GetBuffer());

	m_nNumRules = m_pRuleBook->GetNumRules();
	m_ulRuleBw = new UINT32[m_nNumRules];
	m_ulRulePreData = new UINT32[m_nNumRules];
	m_bRuleTimeStampDelivery = new BOOL[m_nNumRules];
	m_pSubInfo = new BOOL[m_nNumRules];
	m_pRuleSubscribeStatus = new BOOL[m_nNumRules];

        for (UINT16 i = 0; i < m_nNumRules; i++)
        {
	    IHXValues*	pValues;
	    IHXBuffer* pBuffer;

	    m_pRuleBook->GetProperties(i, pValues);

	    m_ulRuleBw[i] = 0;
	    m_ulRulePreData[i] = 0;
	    m_bRuleTimeStampDelivery[i] = FALSE;

	    if (HXR_OK == pValues->GetPropertyCString("PreData",
		pBuffer))
	    {
		m_ulRulePreData[i] = atoi((char*)pBuffer->GetBuffer());
		pBuffer->Release();
	    }

	    if (HXR_OK == pValues->GetPropertyCString("AverageBandwidth",
		pBuffer))
	    {
		m_ulRuleBw[i] = atoi((char*)pBuffer->GetBuffer());
		pBuffer->Release();
	    }
	    else if (HXR_OK == pValues->GetPropertyCString("TimeStampDelivery",
		pBuffer))
	    {
		if ((pBuffer->GetBuffer()[0] == 'T') ||
		    (pBuffer->GetBuffer()[0] == 't'))
		{
		    // Handle TimeStamp Delivery (i.e. assume significant bandwidth)
		    m_ulRuleBw[i] = 0;
		    m_bRuleTimeStampDelivery[i] = TRUE;
		}
		pBuffer->Release();
	    }
	    else
	    {
		/* XXXSMP Temporary hack for invalid rulebooks */
		if (i == 0)
		{
		    IHXValues* pHeader = 0;

		    HX_VERIFY(pHeader = pStream->GetHeader());
		    pHeader->GetPropertyULONG32("AvgBitRate",m_ulRuleBw[i]);
		    pHeader->Release();
		}
		else
		{
		    m_ulRuleBw[i] = 0;
		}
	    }
	    pValues->Release();

            m_pSubInfo[i] = 0;
	    m_pRuleSubscribeStatus[i] = FALSE;
        }

	BOOL bFixed = TRUE;

	m_bHasExpression = m_pRuleBook->HasExpression();
	if (m_bHasExpression == FALSE)
	{
	    UINT16 i;
	    for (i = 0; i < m_nNumRules; i++)
	    {
		if (m_bRuleTimeStampDelivery[i] == FALSE)
		{
		    bFixed = FALSE;
		    break;
		}
	    }

	    if (bFixed)
	    {
		m_ulFixedBandwidth = 1;
	    }
	    else
	    {
		m_ulCurrentBandwidth = 0;
		for (i = 0; i < m_nNumRules; i++)
		{
		    m_ulCurrentBandwidth += m_ulRuleBw[i];
		}

		m_ulFixedBandwidth = m_ulCurrentBandwidth;
	    }
	}
    }
    else
    {
	IHXValues* pHeader = 0;

	HX_VERIFY(pHeader = pStream->GetHeader());
	HX_VERIFY(HXR_OK == pHeader->GetPropertyULONG32("AvgBitRate",
	    m_ulFixedBandwidth));
	
	m_ulCurrentBandwidth = m_ulFixedBandwidth; 

	pHeader->Release();
    }

    /* Get Registry ID's for interesting properties */
    IHXBuffer* pPropName = 0;

    // init. 
    memset(m_szRecv, 0, MAX_DISPLAY_NAME);
    memset(m_szLost, 0, MAX_DISPLAY_NAME);
    memset(m_szClipBandwidth, 0, MAX_DISPLAY_NAME);

    if( m_pRegistry )
	{
	    m_pRegistry->GetPropName(ulStreamID, pPropName);
	}
    
    if (pPropName)
    {
	SafeSprintf(m_szRecv, MAX_DISPLAY_NAME, "%s.received", pPropName->GetBuffer());
	m_ulIDRecv = m_pRegistry->GetId(m_szRecv);

	SafeSprintf(m_szLost, MAX_DISPLAY_NAME, "%s.lost", pPropName->GetBuffer());
	m_ulIDLost = m_pRegistry->GetId(m_szLost);

	SafeSprintf(m_szClipBandwidth, MAX_DISPLAY_NAME, "%s.ClipBandwidth", pPropName->GetBuffer());
	m_ulIDClipBandwidth = m_pRegistry->GetId(m_szClipBandwidth);
	pPropName->Release();
    }

    /* 
     * We consider Local source as a Network source IFF someone uses core
     * for simulated network playback (used for Preview mode in the Encoder)
     */
    if (pSource->IsLocalSource() && !pSource->IsSimulatedNetworkPlayback())
    {
	/* Some large bandwidth */
	m_ulBandwidthAllocation = 0x7FFFFFFF;
	BOOL b;
	SetBandwidthUsage(m_ulBandwidthAllocation, b);
    }
    else if (pSource->IsPNAProtocol())
    {
	IHXBuffer* pMimeType = NULL;
	m_pHeader->GetPropertyCString("MimeTYpe", pMimeType);

	if (pMimeType && 
	    ::strcasecmp((const char*) pMimeType->GetBuffer(), "audio/x-pn-realaudio") == 0)
	{
	    /* Some large bandwidth */
	    m_ulBandwidthAllocation = 0x7FFFFFFF;
	    BOOL b;
	    SetBandwidthUsage(m_ulBandwidthAllocation, b);
	}
	HX_RELEASE(pMimeType);
    }
    else if (pRuleBook)
    {
	m_pLossCB = new LossCheckCallback(this);
	m_pLossCB->AddRef();
	m_ulLossCBHandle = m_pScheduler->RelativeEnter(m_pLossCB, 1000);
    }
    
    HX_RELEASE(pRuleBook);
}

HXASMStream::~HXASMStream()
{
#ifndef GOLD
    HX_RELEASE(m_pEM);
#endif

    if (m_ulLossCBHandle)
    {
        m_pScheduler->Remove(m_ulLossCBHandle);
        m_ulLossCBHandle = 0;
    }

    HX_RELEASE(m_pLossCB);

    HX_VECTOR_DELETE(m_pSubInfo);
    HX_VECTOR_DELETE(m_ulRuleBw);
    HX_VECTOR_DELETE(m_ulRulePreData);
    HX_VECTOR_DELETE(m_bRuleTimeStampDelivery);
    HX_VECTOR_DELETE(m_pRuleSubscribeStatus);
    
    HX_RELEASE(m_pASMSource);
    HX_RELEASE(m_pAtomicRuleChange);
    HX_RELEASE(m_pSource);
    HX_RELEASE(m_pHeader);
    HX_RELEASE(m_pRegistry);
    HX_RELEASE(m_pScheduler);

    CHXMapPtrToPtr::Iterator lIterator =  m_pStreamSinkMap->Begin();
    for (; lIterator != m_pStreamSinkMap->End(); ++lIterator)
    {
	IHXASMStreamSink* pASMStreamSink = 
		(IHXASMStreamSink*) *lIterator;
	pASMStreamSink->Release();
    }
    m_pStreamSinkMap->RemoveAll();

    HX_DELETE(m_pASMRuleState);
    HX_DELETE(m_pRuleBook);
    HX_RELEASE(m_pSubscriptionVariables);
    HX_DELETE(m_pStreamSinkMap);
}

STDMETHODIMP_(UINT32)
HXASMStream::AddRef(void)
{
    return InterlockedIncrement(&m_lRefCount);
}

STDMETHODIMP_(UINT32)
HXASMStream::Release(void)
{
    if (InterlockedDecrement(&m_lRefCount) > 0)
    {
	return m_lRefCount;
    }

    delete this;
    return 0;
}

STDMETHODIMP
HXASMStream::QueryInterface
(
    REFIID interfaceID,
    void** ppInterfaceObj
)
{
    QInterfaceList qiList[] =
        {
            { GET_IIDHANDLE(IID_IHXASMStream), (IHXASMStream*)this },
            { GET_IIDHANDLE(IID_IHXASMStream2), (IHXASMStream2*)this },
            { GET_IIDHANDLE(IID_IHXStreamBandwidthNegotiator), (IHXStreamBandwidthNegotiator*)this },
            { GET_IIDHANDLE(IID_IHXStreamBandwidthBias), (IHXStreamBandwidthBias*)this },
            { GET_IIDHANDLE(IID_IHXASMProps), (IHXASMProps*)this },
            { GET_IIDHANDLE(IID_IHXAtomicRuleGather), (IHXAtomicRuleGather*)this },
            { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXASMStream*)this },
        };
    
    return ::QIFind(qiList, QILISTSIZE(qiList), interfaceID, ppInterfaceObj);
}

/*
 * IHXASMStream methods
 */

/************************************************************************
 *	Method:
 *	    IHXASMStream::AddStreamSink
 *	Purpose:
 *
 */
STDMETHODIMP
HXASMStream::AddStreamSink(IHXASMStreamSink* pASMStreamSink)
{
    HX_ASSERT(pASMStreamSink);

    if (!pASMStreamSink)
    {
	return HXR_UNEXPECTED;
    }

    void* pTmp;
    if (m_pStreamSinkMap->Lookup((void*) pASMStreamSink, pTmp))
    {
	return HXR_UNEXPECTED;
    }

    pASMStreamSink->AddRef();
    m_pStreamSinkMap->SetAt((void*) pASMStreamSink, (void*) pASMStreamSink);

    return HXR_OK;
}

/************************************************************************
 *	Method:
 *	    IHXASMStream::RemoveStreamSink
 *	Purpose:
 *
 */
STDMETHODIMP
HXASMStream::RemoveStreamSink(IHXASMStreamSink* pASMStreamSink)
{
    HX_ASSERT(pASMStreamSink && m_pASMSource);

    if (!pASMStreamSink)
    {
	return HXR_UNEXPECTED;
    }

    void* pTmp;
    if (!m_pStreamSinkMap->Lookup((void*) pASMStreamSink, pTmp))
    {
	return HXR_UNEXPECTED;
    }

    pASMStreamSink->Release();
    m_pStreamSinkMap->RemoveKey((void*) pASMStreamSink);

    return HXR_OK;
}

STDMETHODIMP
HXASMStream::Subscribe(UINT16 uRuleNumber)
{
    HX_RESULT lResult = HXR_OK;

    if (!m_pASMSource)
    {
	return HXR_OK;
    }

    DEBUG_OUT(m_pEM, DOL_ASM, (s, "(%p)Subscribe: Stream=%d Rule=%d", m_pSource, m_uStreamNumber, uRuleNumber));

    m_pRuleSubscribeStatus[uRuleNumber] = TRUE;
    
    if (m_pASMRuleState)
    {
	m_pASMRuleState->CompleteSubscribe(uRuleNumber);
	m_pASMRuleState->StartUnsubscribePending(uRuleNumber);
    }

    if (m_pAtomicRuleChange)
    {
	lResult = HXR_OK;
    }
    else
    {
	lResult = m_pASMSource->Subscribe(m_uStreamNumber, uRuleNumber); 
    }
    if (lResult == HXR_OK)
    {
	CHXMapPtrToPtr::Iterator lIterator =  m_pStreamSinkMap->Begin();
	for (;	(lIterator != m_pStreamSinkMap->End()) && lResult == HXR_OK; 
		++lIterator)
	{
	    IHXASMStreamSink* pASMStreamSink = 
		    (IHXASMStreamSink*) *lIterator;
	    lResult = pASMStreamSink->OnSubscribe(uRuleNumber);
	}
    }
    
    return lResult;
}

STDMETHODIMP
HXASMStream::Unsubscribe(UINT16	uRuleNumber)
{
    HX_RESULT lResult = HXR_OK;

    if (!m_pASMSource)
    {
	return HXR_OK;
    }

    DEBUG_OUT(m_pEM, DOL_ASM, (s, "(%p)Unsubscribe: Stream=%d Rule=%d", m_pSource, m_uStreamNumber, uRuleNumber));

    m_pRuleSubscribeStatus[uRuleNumber] = FALSE;
    
    if (m_pASMRuleState)
    {
	m_pASMRuleState->CompleteUnsubscribe(uRuleNumber);
    }

    if (m_pAtomicRuleChange)
    {
	lResult = HXR_OK;
    }
    else
    {
	lResult = m_pASMSource->Unsubscribe(m_uStreamNumber, uRuleNumber); 
    }
    if (lResult == HXR_OK)
    {
	CHXMapPtrToPtr::Iterator lIterator =  m_pStreamSinkMap->Begin();
	for (;	(lIterator != m_pStreamSinkMap->End()) && lResult == HXR_OK; 
		++lIterator)
	{
	    IHXASMStreamSink* pASMStreamSink = 
		    (IHXASMStreamSink*) *lIterator;
	    lResult = pASMStreamSink->OnUnsubscribe(uRuleNumber);
	}
    }
    
    return lResult;
}



/*
 * This is actually just a negotiation interface.  We need an interface
 * that tells us the actual allotment after oversend so that we can have
 * some more bandwidth available in case something like this happens:
 *  0 - 8k
 *  1 - 16k
 *  2 - 1k ECC for 0
 *  3 - 2k ECC for 1
 *  In this case, we need extra bandwidth already available to go and
 *  add 3 to 1
 */
STDMETHODIMP
HXASMStream::SetBandwidthUsage(REF(UINT32) ulRecvBitRate,
			       REF(BOOL) bTimeStampDelivery)
{
    if (m_pRuleBook == NULL)
    {
	return HXR_OK;
    }

    m_ulBandwidthAllocation = ulRecvBitRate;

    /*
     * This appears to be a var to make sure that Recalc only
     * does things when called from certain places.  I am not sure.
     */
    m_bStartRecalc = TRUE;
    Recalc();


⌨️ 快捷键说明

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