hxsmstr.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:29k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: hxsmstr.cpp,v 1.13.2.1 2004/07/09 02:05:30 hubbe Exp $
- *
- * Portions Copyright (c) 1995-2004 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 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (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.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * 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();
- /*
- * Add up the bitrate of all of the rules we are subscribed to
- * and check if any of the rules put us in time stamped delivery mode.
- */
- ulRecvBitRate = 0;
- m_bTimeStampDeliveryMode = FALSE;
- for (UINT16 i = 0; i < m_nNumRules; i++)
- {
- if (m_pSubInfo[i])
- {
- ulRecvBitRate += m_ulRuleBw[i];
- if(m_bRuleTimeStampDelivery[i])
- {
- m_bTimeStampDeliveryMode = TRUE;
- }
- }
- }
- bTimeStampDelivery = m_bTimeStampDeliveryMode;
- return HXR_OK;
- }
- STDMETHODIMP
- HXASMStream::HandleSlowSource(UINT32 ulRecvBitRate)
- {
- #if XXXSMP
- /* Whoa! This code is totally buggy. We need to fix this!
- *
- * This code was NEVER executed, since day 1. Since I fixed the TS
- * delivery flag above, we started executing it (and it doesn't work).
- *
- * Besides, not executing it is a good thing- This mode really sucks.
- */
- if (m_bTimeStampDeliveryMode)
- #else
- if (0)
- #endif
- {
- /*
- * Time stamp delivery mode. No amount of ASM can help us now.
- */
- /*
- * If we are above what we previously asked the server to limit to
- * then we have not yet started receiving the slower data yet or
- * the server is ignoring us. Either way it will not help to send
- * the message again.
- */
- if(ulRecvBitRate >= m_ulLastLimitBandwidth)
- {
- return HXR_OK;
- }
- IHXThinnableSource* pThin;
- if(HXR_OK == m_pASMSource->QueryInterface(IID_IHXThinnableSource,
- (void **)&pThin))
- {
- /*
- * Tell the source to thin the bitrate down to 80% of what we
- * were getting.
- */
- m_ulLastLimitBandwidth = (UINT32)(0.8 * ulRecvBitRate);
- pThin->LimitBandwidthByDropping(m_uStreamNumber, m_ulLastLimitBandwidth);
- pThin->Release();
- }
- }
- return HXR_OK;
- }
- STDMETHODIMP
- HXASMStream::GetThresholdInfo(float* pThreshold, REF(UINT32) ulNumThreshold)
- {
- // XXXSMP Fix this. Unify all construction of buffers & values
- // to one place. Don't reconstruct unless you need to and store wasting
- // time, space, memory!
- if (!m_pRuleBook)
- {
- // ASM always expect num of threshold >= 1
- ulNumThreshold = 1;
- pThreshold[0] = 0.0f;
-
- return HXR_OK;
- }
- HXSMUpdateSubscriptionVars(m_pSubscriptionVariables, 0,
- TRUE, ComputeLost());
- m_pRuleBook->GetPreEvaluate(pThreshold, ulNumThreshold,
- m_pSubscriptionVariables, "Bandwidth");
- return HXR_OK;
- }
- STDMETHODIMP
- HXASMStream::UnRegister(void)
- {
- m_bStartRecalc = FALSE;
- /* Remove any scheduled callback */
- if (m_ulLossCBHandle && m_pLossCB && m_pScheduler)
- {
- m_pScheduler->Remove(m_ulLossCBHandle);
- m_ulLossCBHandle = 0;
- }
-
- return HXR_OK;
- }
- STDMETHODIMP_(ULONG32)
- HXASMStream::GetNumThresholds(void)
- {
- // return the maximum number of thresholds for this rulebook
- return m_pRuleBook ? m_pRuleBook->GetNumThresholds(): 0;
- }
- STDMETHODIMP
- HXASMStream::GetFixedBandwidth(REF(UINT32) ulBitRate)
- {
- if (m_ulFixedBandwidth)
- {
- ulBitRate = m_ulFixedBandwidth;
- return HXR_OK;
- }
- return HXR_FAIL;
- }
- STDMETHODIMP
- HXASMStream::GetBiasFactor(REF(INT32) lBias)
- {
- lBias = m_lBias;
- return HXR_OK;
- }
- STDMETHODIMP
- HXASMStream::SetBiasFactor(INT32 lBias)
- {
- m_lBias = lBias;
- return HXR_OK;
- }
- HXASMStream::LossCheckCallback::LossCheckCallback(HXASMStream* pASMStream)
- {
- m_pASMStream = pASMStream;
- m_lRefCount = 0;
- }
- STDMETHODIMP_(UINT32)
- HXASMStream::LossCheckCallback::AddRef(void)
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- STDMETHODIMP_(UINT32)
- HXASMStream::LossCheckCallback::Release(void)
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- STDMETHODIMP
- HXASMStream::LossCheckCallback::QueryInterface
- (
- REFIID interfaceID,
- void** ppInterfaceObj
- )
- {
- QInterfaceList qiList[] =
- {
- { GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*)this },
- { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXCallback*)this },
- };
-
- return ::QIFind(qiList, QILISTSIZE(qiList), interfaceID, ppInterfaceObj);
- }
- STDMETHODIMP
- HXASMStream::GetPreData(REF(UINT32) ulPreData)
- {
- if (m_ulCurrentPreData)
- {
- ulPreData = m_ulCurrentPreData;
- return HXR_OK;
- }
- else
- {
- ulPreData = 0;
- return HXR_FAIL;
- }
- }
- STDMETHODIMP
- HXASMStream::GetBandwidth(REF(UINT32) ulBandwidth)
- {
- if (m_ulCurrentBandwidth)
- {
- ulBandwidth = m_ulCurrentBandwidth;
- return HXR_OK;
- }
- else if (m_ulLastBandwidth)
- {
- ulBandwidth = m_ulLastBandwidth;
- return HXR_OK;
- }
- else
- {
- ulBandwidth = 0;
- return HXR_FAILED;
- }
- }
- void
- HXASMStream::RecalcCurrentProps()
- {
- m_ulCurrentBandwidth = 0;
- m_ulCurrentPreData = 0;
- for (UINT16 i = 0; i < m_nNumRules; i++)
- {
- if (m_pSubInfo[i])
- {
- m_ulCurrentPreData += m_ulRulePreData[i];
- m_ulCurrentBandwidth += m_ulRuleBw[i];
- }
- }
- if (m_pSource->IsActive())
- {
- INT32 lLastBandwidth = 0;
- if( m_pRegistry )
- {
- m_pRegistry->GetIntById(m_ulIDClipBandwidth, lLastBandwidth);
- }
- /* Do not override bandwidth if the current bandwidth has either
- * not changed or is zero.
- */
- if (m_ulCurrentBandwidth != 0 &&
- (UINT32) lLastBandwidth != m_ulCurrentBandwidth &&
- m_pRegistry)
- {
- m_pRegistry->SetIntById(m_ulIDClipBandwidth, m_ulCurrentBandwidth);
- /* A hack to tell the top level client that a stream switch occured */
- m_pRegistry->SetIntByName("Statistics.StreamSwitchOccured", 1);
- }
- }
- if (m_ulCurrentBandwidth > 0)
- {
- m_ulLastBandwidth = m_ulCurrentBandwidth;
- }
-
- //DEBUG_OUT(this, (s, "New PreData %p %d New Bandwidth %dn", this, m_ulCurrentPreData, m_ulCurrentBandwidth));
- }
- void
- HXASMStream::Recalc()
- {
- if (!m_bStartRecalc)
- return;
- HXSMUpdateSubscriptionVars(m_pSubscriptionVariables,
- m_ulBandwidthAllocation,
- TRUE, ComputeLost());
- BOOL* pCurrentSubInfo = new BOOL[m_nNumRules];
-
- if (m_pRuleBook)
- {
- HX_RESULT lResult = m_pRuleBook->GetSubscription(pCurrentSubInfo, m_pSubscriptionVariables);
- HX_ASSERT(lResult == HXR_OK);
- }
- CHXSimpleList SubChange;
- CHXSimpleList* pSubList = &SubChange;
- if (m_pSubList)
- {
- pSubList = m_pSubList;
- }
- for (UINT16 i = 0; i < m_nNumRules; i++)
- {
- if (pCurrentSubInfo[i] != m_pSubInfo[i])
- {
- RTSPSubscription* pEntry = NULL;
- if (m_pAtomicRuleChange)
- {
- pEntry = new RTSPSubscription;
- pEntry->m_streamNumber = m_uStreamNumber;
- pEntry->m_ruleNumber = i;
- pEntry->m_bIsSubscribe = (pCurrentSubInfo[i]) ? TRUE : FALSE;
- pSubList->AddTail(pEntry);
- }
- if (pCurrentSubInfo[i])
- {
- Subscribe(i);
- }
- else
- {
- Unsubscribe(i);
- }
- m_pSubInfo[i] = pCurrentSubInfo[i];
- }
- }
- if (m_pAtomicRuleChange && (!m_pSubList) && (!SubChange.IsEmpty()))
- {
- m_pAtomicRuleChange->RuleChange(SubChange);
- }
- RecalcCurrentProps();
- delete [] pCurrentSubInfo;
- /* Reschedule callback if this was invoked by the scheduler callback */
- if (!m_ulLossCBHandle && m_pLossCB)
- {
- m_ulLossCBHandle = m_pScheduler->RelativeEnter(m_pLossCB, 1000);
- }
- }
- float HXASMStream::ComputeLost()
- {
- INT32 ulRecv = 0, ulLost = 0;
- float lost = 0.0;
-
- if( m_pRegistry )
- {
- m_pRegistry->GetIntById(m_ulIDRecv, ulRecv);
- m_pRegistry->GetIntById(m_ulIDLost, ulLost);
- }
- if (ulRecv != 0)
- {
- lost = ((float)ulLost) / ((float)ulRecv) * 100;
- }
- return lost;
- }
- STDMETHODIMP
- HXASMStream::LossCheckCallback::Func()
- {
- m_pASMStream->m_ulLossCBHandle = 0;
- m_pASMStream->Recalc();
- return HXR_OK;
- }
- HX_RESULT
- HXASMStream::ResetASMSource(IHXASMSource* pASMSource)
- {
- HX_RESULT hr = HXR_OK;
- HX_RELEASE(m_pASMSource);
- if (pASMSource)
- {
- pASMSource->QueryInterface(IID_IHXASMSource, (void **)&m_pASMSource);
- }
- if (m_pAtomicRuleChange)
- {
- HX_RELEASE(m_pAtomicRuleChange);
- pASMSource->QueryInterface(IID_IHXAtomicRuleChange,
- (void **)&m_pAtomicRuleChange);
- }
- // reset substream info.
- if (m_pRuleBook && m_pSubInfo)
- {
- for (UINT16 i = 0; i < m_nNumRules; i++)
- {
- m_pSubInfo[i] = 0;
- }
- }
- // reset Registry ID
- if (strlen(m_szRecv) && m_pRegistry)
- {
- m_ulIDRecv = m_pRegistry->GetId(m_szRecv);
- }
- if (strlen(m_szLost) && m_pRegistry)
- {
- m_ulIDLost = m_pRegistry->GetId(m_szLost);
- }
- if (strlen(m_szClipBandwidth) && m_pRegistry)
- {
- m_ulIDClipBandwidth = m_pRegistry->GetId(m_szClipBandwidth);
- }
- return hr;
- }
- STDMETHODIMP
- HXASMStream::RuleGather(CHXSimpleList* pList)
- {
- /* Truely disgusting... */
- m_pSubList = pList;
- return HXR_OK;
- }
- STDMETHODIMP
- HXASMStream::RuleFlush(CHXSimpleList* pList)
- {
- m_pAtomicRuleChange->RuleChange(*pList);
- return HXR_OK;
- }
- void
- HXASMStream::PostEndTimePacket(IHXPacket* pPacket, BOOL& bSentMe, BOOL& bEndMe)
- {
- int i = 0;
- UINT8 nRuleFlags = 0;
- UINT16 nRuleNumber = 0;
- IHXBuffer* pRuleBook = NULL;
- bSentMe = TRUE;
- bEndMe = FALSE;
- // assume the packet is NOT lost
- HX_ASSERT(pPacket->IsLost() == FALSE);
- // This is the first packet whose timestamp > endtime
- // Initialize ASMRuleState to determine whether pass it to
- // the renderer or not
- if (!m_pASMRuleState)
- {
- // Extract RuleBook from the stream header
- m_pHeader->GetPropertyCString("ASMRuleBook", pRuleBook);
-
- if (pRuleBook != NULL)
- {
- m_pASMRuleState = new CASMRuleState(m_nNumRules, (char*)pRuleBook->GetBuffer(), (UINT16)pRuleBook->GetSize());
- }
- if (m_pASMRuleState)
- {
- // initialize the ASMRuleState based on the
- // current subscription status of all the rules
- for (i = 0; i < m_nNumRules; i++)
- {
- if (m_pRuleSubscribeStatus[i])
- {
- m_pASMRuleState->CompleteSubscribe(i);
- m_pASMRuleState->StartUnsubscribePending(i);
- }
- }
- }
- else
- {
- // end the stream now is fine.
- bSentMe = FALSE;
- bEndMe = TRUE;
- goto cleanup;
- }
- }
- nRuleNumber = pPacket->GetASMRuleNumber();
- nRuleFlags = pPacket->GetASMFlags();
- // if the rule is unsubscribed, then
- // we just pass it to the renderer since
- // the server will stop sending them anyway
- // i.e. during the stream swithing
- if (!m_pRuleSubscribeStatus[nRuleNumber] &&
- m_pASMRuleState->AnyPendingUnsubscribes())
- {
- goto cleanup;
- }
- else if (nRuleFlags & HX_ASM_SWITCH_OFF)
- {
- if (m_pASMRuleState->IsUnsubscribePending(nRuleNumber) &&
- m_pASMRuleState->CanUnsubscribeNow(nRuleNumber))
- {
- m_pASMRuleState->CompleteUnsubscribe(nRuleNumber);
- }
- }
- bSentMe = m_pASMRuleState->IsRuleSubscribed(nRuleNumber);
- // if all the rules are unsubscribed, then
- // we are DONE!
- if (!m_pASMRuleState->AnyPendingUnsubscribes())
- {
- bSentMe = FALSE;
- bEndMe = TRUE;
- }
- else if (bSentMe == FALSE && m_bEndOneRuleEndAll)
- {
- bEndMe = TRUE;
- }
- cleanup:
- HX_RELEASE(pRuleBook);
- return;
- }
- void
- HXASMStream::ResetASMRuleState(void)
- {
- HX_DELETE(m_pASMRuleState);
- return;
- }
- STDMETHODIMP_(HX_RESULT)
- HXASMStream::Enable( UINT16 nRule )
- {
- if( m_pRuleBook )
- {
- m_pRuleBook->Enable( nRule );
- }
- return HXR_OK;
- }
- STDMETHODIMP_(HX_RESULT)
- HXASMStream::Disable( UINT16 nRule )
- {
- if( m_pRuleBook )
- {
- m_pRuleBook->Disable( nRule );
- }
- return HXR_OK;
- }
- STDMETHODIMP_(HX_RESULT)
- HXASMStream::ReCompute()
- {
- HX_RESULT retVal = HXR_OK;
- if( m_pRuleBook )
- {
- m_pRuleBook->ReCompute();
- // Now we must check that there is at least 1 playable substream.
- BOOL* pCurrentSubInfo = new BOOL[m_nNumRules];
- if( pCurrentSubInfo == NULL )
- {
- return HXR_FAIL;
- }
-
- HXSMUpdateSubscriptionVars(m_pSubscriptionVariables, 0, FALSE, 0);
- // GetSubscription does not actually do any subscribing. Rather it
- // populates the boolean array pCurrentSubInfo such that subscribable
- // streams are set to TRUE;
- m_pRuleBook->GetSubscription( pCurrentSubInfo, m_pSubscriptionVariables );
- BOOL bAtLeastOneRuleSubscribable = FALSE;
- for( int ii=0; ii<m_nNumRules; ii++ )
- {
- if( pCurrentSubInfo[ii] == TRUE )
- {
- bAtLeastOneRuleSubscribable = TRUE;
- }
- }
- HX_VECTOR_DELETE(pCurrentSubInfo);
- if( bAtLeastOneRuleSubscribable == FALSE )
- {
- // We can't subscribe to any stream so reset and fail.
- for( int ii=0; ii<m_nNumRules; ii++ )
- {
- m_pRuleBook->Enable( ii );
- }
- m_pRuleBook->ReCompute();
- retVal = HXR_FAIL;
- }
- }
- return retVal;
- }