hxsm2.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:30k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: hxsm2.cpp,v 1.9.8.2 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 "hxsm2.h"
- #include "hxsmutil.h"
- #include "ihxpckts.h"
- #include "hxprefs.h"
- #include "hxpref.h"
- #include "hxbsrc.h" /* HXSource */
- #include "asmrulep.h" /* ASMRuleBook */
- #include "hxbuffer.h" /* CHXBuffer */
- #include "chxpckts.h" /* CHXHeader */
- #include "safestring.h" /* SafeSprintf */
- #include "rtspif.h" /* RTSPSubscription */
- class ASMStreamInfo2;
- class ASMSourceInfo2
- {
- public:
- ASMSourceInfo2(HXSource* pSource);
- ~ASMSourceInfo2();
- UINT32 StreamCount() const;
- ASMStreamInfo2* GetStream(UINT32 i);
- UINT32& SubscribeBw();
- UINT32& LastSetDelivery();
- UINT32& MasterOffer();
- BOOL IsMySource(HXSource* pSource);
- BOOL IsLive();
- BOOL IsPerfectPlay() const;
- BOOL HasMasterRuleBook() const;
- void DistributeBw();
- CHXSimpleList* SubsChanges();
- void SubscribeToChanges();
- void SetDeliveryBw(UINT32 ulMaxBw);
- void Done();
- private:
- HX_RESULT GetSubInfo(UINT32 ulBandwidth,
- BOOL* pCurrentSubInfo);
- UINT32 GetStreamBw(IHXValues* pProps,
- UINT32 ulStreamIndex) const;
- HXSource* m_pSource;
- UINT32 m_ulStreamCount;
- ASMStreamInfo2** m_pStreams;
- UINT32 m_ulSubscribedBw;
- UINT32 m_ulLastSetDelivery;
- UINT32 m_ulMasterOffer;
- BOOL m_bPerfectPlay;
- ASMRuleBook* m_pMasterRuleBook;
- IHXValues* m_pSubsVars;
- CHXSimpleList m_subsChanges;
- };
- class ASMStreamInfo2
- {
- public:
- ASMStreamInfo2(IUnknown* pStream);
- ~ASMStreamInfo2();
- HX_RESULT GetBiasFactor(REF(INT32) lBiasFactor);
- BOOL IsFixedBw() const;
- UINT32 CurrentBw() const;
- UINT32 StreamID() const;
-
- void SetStreamOffer(UINT32 ulOffer);
- void SelectBw(BOOL bPerfectPlay,
- UINT32 ulAltOffer);
-
- UINT32 ResistanceToLower() const;
- void SelectNextLowerBw();
- UINT32 GetLastBw() const;
- void SubscribeToNewBw(UINT32 ulBw, CHXSimpleList* pSubChanges);
- void SubscribeToChanges(CHXSimpleList* pSubChanges);
- private:
- void ComputeResistence(BOOL bPerfectPlay);
- BOOL m_bFixedBwValid;
- UINT32 m_ulFixedBandwidth;
- UINT32 m_ulNumThresholds;
- float* m_pThresholds;
- UINT32 m_ulCurThresh;
- UINT32 m_ulMaxEffectiveThreshold;
- IHXStreamBandwidthBias* m_pBias;
- IHXStreamBandwidthNegotiator* m_pNegotiator;
- IHXAtomicRuleGather* m_pRuleGather;
- UINT32 m_ulStreamID;
- UINT32 m_ulStreamOffer; // From master rulebook
- UINT32 m_ulOffer; // From SelectBw()
- UINT32 m_ulResistanceToLower;
- UINT32 m_ulLastBw;
- };
- class ASMStreamInfoItr
- {
- public:
- ASMStreamInfoItr(CHXSimpleList* pSourceList);
-
- ASMSourceInfo2* Source();
- ASMStreamInfo2* Stream();
- BOOL More() const;
- void Next();
- void Reset();
- private:
- void FindNextSource();
- CHXSimpleList* m_pSourceList;
- CHXSimpleList::Iterator m_itr;
- UINT32 m_ulStream;
- };
- ASMStreamInfoItr::ASMStreamInfoItr(CHXSimpleList* pSourceList) :
- m_pSourceList(pSourceList),
- m_ulStream(0)
- {
- Reset();
- }
- ASMSourceInfo2* ASMStreamInfoItr::Source()
- {
- ASMSourceInfo2* pRet = 0;
-
- if (More())
- {
- pRet = (ASMSourceInfo2*)(*m_itr);
- }
- return pRet;
- }
- ASMStreamInfo2* ASMStreamInfoItr::Stream()
- {
- ASMStreamInfo2* pRet = 0;
-
- ASMSourceInfo2* pSrc = Source();
- if (pSrc)
- {
- pRet = pSrc->GetStream(m_ulStream);
- }
- return pRet;
- }
- BOOL ASMStreamInfoItr::More() const
- {
- return (m_pSourceList &&
- (m_itr != m_pSourceList->End()));
- }
- void ASMStreamInfoItr::Next()
- {
- if (More())
- {
- m_ulStream++;
- if (m_ulStream == Source()->StreamCount())
- {
- // We are done with this source.
- // Move onto the next one
- m_ulStream = 0;
- ++m_itr;
- FindNextSource();
- }
- }
- }
- void ASMStreamInfoItr::Reset()
- {
- if (m_pSourceList)
- {
- m_ulStream = 0;
-
- m_itr = m_pSourceList->Begin();
- FindNextSource();
- }
- }
- void ASMStreamInfoItr::FindNextSource()
- {
- BOOL bDone = FALSE;
- while(!bDone && m_itr != m_pSourceList->End())
- {
- ASMSourceInfo2* pSrc = (ASMSourceInfo2*)(*m_itr);
-
- if (pSrc && pSrc->StreamCount() > 0)
- {
- bDone = TRUE;
- }
- else
- {
- ++m_itr;
- }
- }
- }
- ASMSourceInfo2::ASMSourceInfo2(HXSource* pSource) :
- m_pSource(pSource),
- m_ulStreamCount(0),
- m_pStreams(0),
- m_ulSubscribedBw(0),
- m_ulLastSetDelivery(0),
- m_ulMasterOffer(0),
- m_bPerfectPlay(FALSE),
- m_pMasterRuleBook(0),
- m_pSubsVars(0)
- {
- if (m_pSource)
- {
- m_pSource->AddRef();
- m_bPerfectPlay = m_pSource->IsPerfectPlay();
- m_ulStreamCount = pSource->GetStreamCount();
- m_pStreams = new ASMStreamInfo2*[m_ulStreamCount];
- if (m_pStreams)
- {
- for (UINT32 i = 0; i < m_ulStreamCount; i++)
- {
- IUnknown* pStream = 0;
- HX_VERIFY(HXR_OK == pSource->GetStream(i, pStream));
- m_pStreams[i] = new ASMStreamInfo2(pStream);
-
- HX_RELEASE(pStream);
- }
- }
- // Get Master Rulebook
- if (pSource->m_pFileHeader)
- {
- IHXBuffer* pMasterRuleBook = NULL;
- pSource->m_pFileHeader->
- GetPropertyCString("ASMRuleBook", pMasterRuleBook);
-
- if (pMasterRuleBook)
- {
- m_pMasterRuleBook = new ASMRuleBook
- ((const char *)pMasterRuleBook->GetBuffer());
- }
-
- HX_RELEASE(pMasterRuleBook);
- }
- }
- }
- ASMSourceInfo2::~ASMSourceInfo2()
- {
- if (m_pStreams)
- {
- for (UINT32 i = 0; i < m_ulStreamCount; i++)
- {
- delete m_pStreams[i];
- m_pStreams[i] = 0;
- }
- delete [] m_pStreams;
- }
- HX_RELEASE(m_pSource);
- HX_RELEASE(m_pSubsVars);
- delete m_pMasterRuleBook;
- m_pMasterRuleBook = 0;
- }
- inline
- UINT32 ASMSourceInfo2::StreamCount() const
- {
- return m_ulStreamCount;
- }
- ASMStreamInfo2* ASMSourceInfo2::GetStream(UINT32 i)
- {
- ASMStreamInfo2* pRet = 0;
- if (m_pStreams && (i < m_ulStreamCount))
- {
- pRet = m_pStreams[i];
- }
- return pRet;
- }
- inline
- UINT32& ASMSourceInfo2::SubscribeBw()
- {
- return m_ulSubscribedBw;
- }
- inline
- UINT32& ASMSourceInfo2::LastSetDelivery()
- {
- return m_ulLastSetDelivery;
- }
- inline
- UINT32& ASMSourceInfo2::MasterOffer()
- {
- return m_ulMasterOffer;
- }
- inline
- BOOL ASMSourceInfo2::IsMySource(HXSource* pSource)
- {
- return (m_pSource == pSource);
- }
- BOOL ASMSourceInfo2::IsLive()
- {
- BOOL bRet = FALSE;
- if (m_pSource)
- {
- bRet = m_pSource->IsLive();
- }
- return bRet;
- }
- inline
- BOOL ASMSourceInfo2::IsPerfectPlay() const
- {
- return m_bPerfectPlay;
- }
- inline
- BOOL ASMSourceInfo2::HasMasterRuleBook() const
- {
- return (m_pMasterRuleBook != NULL);
- }
- void ASMSourceInfo2::DistributeBw()
- {
- if (m_pMasterRuleBook)
- {
- UINT32 ulRuleCount = m_pMasterRuleBook->GetNumRules();
- BOOL* pCurrentSubInfo = new BOOL[ulRuleCount];
- GetSubInfo(m_ulMasterOffer, pCurrentSubInfo);
- for (UINT16 idxRule = 0; idxRule < ulRuleCount; idxRule++)
- {
- if (pCurrentSubInfo[idxRule])
- {
- IHXValues* pProps = 0;
- // Set Distribution
- m_pMasterRuleBook->GetProperties(idxRule, pProps);
- for (UINT32 j = 0; j < m_ulStreamCount; j++)
- {
- UINT32 ulStreamBw = GetStreamBw(pProps, j);
-
- m_pStreams[j]->SetStreamOffer(ulStreamBw);
- }
- HX_RELEASE(pProps);
- break;
- }
- }
- delete [] pCurrentSubInfo;
- }
- }
- inline
- CHXSimpleList* ASMSourceInfo2::SubsChanges()
- {
- return &m_subsChanges;
- }
- void ASMSourceInfo2::SubscribeToChanges()
- {
- if (!m_subsChanges.IsEmpty() && m_pStreams && m_pStreams[0])
- {
- m_pStreams[0]->SubscribeToChanges(&m_subsChanges);
- while(!m_subsChanges.IsEmpty())
- {
- RTSPSubscription* pSub = (RTSPSubscription*)m_subsChanges.RemoveHead();
- delete pSub;
- }
- }
- }
- void ASMSourceInfo2::SetDeliveryBw(UINT32 ulMaxBw)
- {
- if (m_pStreams)
- {
- UINT32 ulTotalBw = 0;
-
- // Calculate the total BW used by the streams
- for (UINT32 i = 0; i < m_ulStreamCount; i++)
- {
- ulTotalBw += m_pStreams[i]->CurrentBw();
- }
- m_ulSubscribedBw = ulTotalBw;
- if (ulTotalBw)
- {
- IHXThinnableSource* pThin = 0;
-
- if (HXR_OK == m_pSource->QueryInterface(IID_IHXThinnableSource,
- (void **)&pThin))
- {
- /* Clamp bandwidth request */
- if (ulTotalBw > ulMaxBw)
- {
- ulTotalBw = ulMaxBw;
- }
-
- pThin->SetDeliveryBandwidth(ulTotalBw, 0);
-
- HX_RELEASE(pThin);
- }
- }
- }
- }
- inline
- void ASMSourceInfo2::Done()
- {
- HX_RELEASE(m_pSource);
- }
- HX_RESULT ASMSourceInfo2::GetSubInfo(UINT32 ulBandwidth,
- BOOL* pCurrentSubInfo)
- {
- HX_RESULT res = HXR_FAILED;
- if (m_pMasterRuleBook)
- {
- res = HXSMUpdateSubscriptionVars(m_pSubsVars, ulBandwidth, FALSE, 0);
- if (HXR_OK == res)
- {
- res = m_pMasterRuleBook->GetSubscription(pCurrentSubInfo,
- m_pSubsVars);
- }
- }
- return res;
- }
- UINT32 ASMSourceInfo2::GetStreamBw(IHXValues* pProps,
- UINT32 ulStreamIndex) const
- {
- UINT32 ulRet = 0;
- UINT8 pTemp[128];
- IHXBuffer* pBw = NULL;
- HX_RESULT hxResult;
-
- // Don't assume that streamid == index in m_pStreams[j]
- sprintf((char *)pTemp,
- "Stream%ldBandwidth",
- m_pStreams[ulStreamIndex]->StreamID()); /* Flawfinder: ignore */
-
- /*
- * if this tripps either there's a bug in here or
- * the content is messed up
- *
- */
- //If the Stream?Bandwidth property isn't found for
- //all streams don't worry about it. Not all streams
- //may have rule books.
- hxResult = pProps->GetPropertyCString((char *)pTemp, pBw);
- if(HXR_OK == hxResult && pBw)
- {
- ulRet = atoi((char*)pBw->GetBuffer());
-
- HX_RELEASE(pBw);
- }
- return ulRet;
- }
- ASMStreamInfo2::ASMStreamInfo2(IUnknown* pStream) :
- m_bFixedBwValid(FALSE),
- m_ulFixedBandwidth(0),
- m_ulNumThresholds(0),
- m_pThresholds(0),
- m_ulCurThresh(0),
- m_ulMaxEffectiveThreshold(0),
- m_pBias(0),
- m_pNegotiator(0),
- m_pRuleGather(0),
- m_ulStreamID(0),
- m_ulStreamOffer(0),
- m_ulOffer(0),
- m_ulResistanceToLower(0xffffffff)
- {
- if (pStream)
- {
- if (HXR_OK == pStream->QueryInterface
- (IID_IHXStreamBandwidthNegotiator,
- (void **)&m_pNegotiator))
- {
- m_pNegotiator->GetFixedBandwidth(m_ulFixedBandwidth);
- if (m_ulFixedBandwidth)
- {
- /* We need to check to see if the fixed bandwidth value
- * matches the ASMProps Bandwidth value. If it doesn't then
- * that means that we are dealing with a clip that doesn't
- * advertise any bandwidth information. This is a corner
- * case discover by streaming some unhinted .3gp files.
- */
- IHXASMProps* pASMProps = NULL;
- UINT32 ulASMBw = 0;
- if ((HXR_OK == pStream->QueryInterface(IID_IHXASMProps,
- (void**)&pASMProps))&&
- (HXR_OK == pASMProps->GetBandwidth(ulASMBw)) &&
- (m_ulFixedBandwidth == ulASMBw))
- {
- m_bFixedBwValid = TRUE;
- }
- HX_RELEASE(pASMProps);
- }
- else
- {
- m_ulNumThresholds = m_pNegotiator->GetNumThresholds();
- m_pThresholds = new float[m_ulNumThresholds];
- if (m_pThresholds)
- {
- m_pNegotiator->GetThresholdInfo(m_pThresholds,
- m_ulNumThresholds);
- m_ulMaxEffectiveThreshold = m_ulNumThresholds - 1;
- }
- }
- }
-
- pStream->QueryInterface(IID_IHXStreamBandwidthBias,
- (void **)&m_pBias);
-
- pStream->QueryInterface(IID_IHXAtomicRuleGather,
- (void **)&m_pRuleGather);
- // Get StreamID
- IHXStream* pHXStream = 0;
- pStream->QueryInterface(IID_IHXStream, (void**)&pHXStream);
- if (pHXStream)
- {
- m_ulStreamID = pHXStream->GetStreamNumber();
- pHXStream->Release();
- }
- }
- }
- ASMStreamInfo2::~ASMStreamInfo2()
- {
- delete [] m_pThresholds;
- m_pThresholds = 0;
- HX_RELEASE(m_pBias);
- HX_RELEASE(m_pNegotiator);
- HX_RELEASE(m_pRuleGather);
- }
- HX_RESULT ASMStreamInfo2::GetBiasFactor(REF(INT32) lBiasFactor)
- {
- HX_RESULT res = HXR_FAILED;
-
- if (m_pBias)
- {
- res = m_pBias->GetBiasFactor(lBiasFactor);
- }
- return res;
- }
- inline
- BOOL ASMStreamInfo2::IsFixedBw() const
- {
- return (m_ulFixedBandwidth != 0);
- }
- UINT32 ASMStreamInfo2::CurrentBw() const
- {
- UINT32 ulRet = (m_bFixedBwValid) ? m_ulFixedBandwidth : 0;
- if (!ulRet && m_pThresholds)
- {
- ulRet = (UINT32)m_pThresholds[m_ulCurThresh];
- }
- return ulRet;
- }
- inline
- UINT32 ASMStreamInfo2::StreamID() const
- {
- return m_ulStreamID;
- }
- inline
- void ASMStreamInfo2::SetStreamOffer(UINT32 ulOffer)
- {
- m_ulStreamOffer = ulOffer;
- }
- void ASMStreamInfo2::SelectBw(BOOL bPerfectPlay,
- UINT32 ulAltOffer)
- {
- if (m_pThresholds)
- {
- if (bPerfectPlay)
- {
- /*
- * If we are in perfect play mode, just select the highest bandwidth rule
- * and don't negotiate any further.
- */
- m_ulCurThresh = m_ulMaxEffectiveThreshold;
- m_ulOffer = CurrentBw();
- }
- else
- {
- UINT32 ulOffer = ulAltOffer;
- if (m_ulStreamOffer)
- {
- ulOffer = m_ulStreamOffer - 1;
- }
-
- if (m_ulMaxEffectiveThreshold != 0)
- {
- for (UINT32 i = 1; i <= m_ulMaxEffectiveThreshold; i++)
- {
- if ((ulOffer <= m_pThresholds[i]) ||
- (i == m_ulMaxEffectiveThreshold))
- {
- m_ulOffer = ulOffer;
- m_ulCurThresh = i;
- break;
- }
- }
- }
- }
- ComputeResistence(bPerfectPlay);
- }
- }
- inline
- UINT32 ASMStreamInfo2::ResistanceToLower() const
- {
- return m_ulResistanceToLower;
- }
- void ASMStreamInfo2::SelectNextLowerBw()
- {
- if (m_ulCurThresh > 0)
- {
- m_ulCurThresh--;
- ComputeResistence(FALSE);
- }
- }
- inline
- UINT32 ASMStreamInfo2::GetLastBw() const
- {
- return m_ulLastBw;
- }
- void ASMStreamInfo2::SubscribeToNewBw(UINT32 ulBw, CHXSimpleList* pSubChanges)
- {
- BOOL bTimeStampDelivery = FALSE;
-
- if (m_pRuleGather && m_pNegotiator)
- {
- m_pRuleGather->RuleGather(pSubChanges);
-
- //update the HXASMStream with our new bandwidth
- m_pNegotiator->SetBandwidthUsage(ulBw, bTimeStampDelivery);
-
- m_pRuleGather->RuleGather(0);
- }
- m_ulLastBw = ulBw;
- }
- void ASMStreamInfo2::SubscribeToChanges(CHXSimpleList* pSubChanges)
- {
- if (m_pRuleGather)
- {
- m_pRuleGather->RuleFlush(pSubChanges);
- }
- }
- void ASMStreamInfo2::ComputeResistence(BOOL bPerfectPlay)
- {
- /* NOTE:
- * m_ulCurThresh and m_ulOffer must
- * be valid when this function is called
- */
- if (IsFixedBw() ||
- bPerfectPlay ||
- (m_ulMaxEffectiveThreshold == 0) ||
- (m_ulCurThresh == 1))
- {
- m_ulResistanceToLower = 0xffffffff;
- }
- else
- {
- m_ulResistanceToLower =
- (m_ulOffer - (UINT32)m_pThresholds[m_ulCurThresh - 1]) * m_ulOffer;
- }
- }
- HXSM2::HXSM2() :
- m_lRefCount(0),
- m_ulNumSources(0),
- m_pASMSourceInfo(0),
- m_ulNumStreams(0),
- m_ulOfferToRecalc(0),
- m_ulSelectionBitRate(0),
- m_ulMaxAccelBitRate(0),
- m_ulSustainableBitRate(0),
- m_pSubscriptionVariables(0),
- m_bCheckOnDemandBw(FALSE)
- {
- m_pASMSourceInfo = new CHXSimpleList();
- }
- HXSM2::~HXSM2()
- {
- if (m_pASMSourceInfo)
- {
- while(!m_pASMSourceInfo->IsEmpty())
- {
- ASMSourceInfo2* pSrc =
- (ASMSourceInfo2*)m_pASMSourceInfo->RemoveHead();
- delete pSrc;
- }
- delete m_pASMSourceInfo;
- }
- }
- STDMETHODIMP HXSM2::QueryInterface(THIS_ REFIID ID, void** ppInterfaceObj)
- {
- QInterfaceList qiList[] =
- {
- { GET_IIDHANDLE(IID_IUnknown), this },
- { GET_IIDHANDLE(IID_IHXBandwidthManager), (IHXBandwidthManager*) this },
- };
- return QIFind(qiList, QILISTSIZE(qiList), ID, ppInterfaceObj);
- }
- STDMETHODIMP_(UINT32) HXSM2::AddRef(THIS)
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- STDMETHODIMP_(UINT32) HXSM2::Release(THIS)
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- /*
- * IHXBandwidthManager methods
- */
- STDMETHODIMP HXSM2::RegisterSource(THIS_
- HXSource* pSource,
- IUnknown* pUnknown)
- {
- HX_RESULT res = HXR_OK;
- IHXSourceBandwidthInfo* pSBI;
- IHXPreferences* pPreferences = NULL;
- IHXBuffer* pBuffer = 0;
- ASMSourceInfo2* pASMSourceInfo = NULL;
- if (HXR_OK == pSource->QueryInterface(IID_IHXSourceBandwidthInfo,
- (void **)&pSBI))
- {
- pASMSourceInfo = new ASMSourceInfo2(pSource);
- m_ulNumSources++;
- m_ulNumStreams += pASMSourceInfo->StreamCount();
- m_pASMSourceInfo->AddTail((void *)pASMSourceInfo);
- HX_RELEASE(pSBI);
- }
- else
- {
- return HXR_OK;
- }
- /*
- * This variable tells us the highest amount of bandwidth that we
- * believe is useable. If we stream thin, then the highest value
- * that the pipe can support would be the aggregate bandwidth of
- * the sources. Barring any thinning, this would be the bandwidth
- * from prefs (unless we can determine it through fast buffering or
- * another transport feature). This value is used when starting sources
- * as a initial guess for bandwidth (to set subscriptions).
- */
- if (m_ulSelectionBitRate == 0)
- {
- pUnknown->QueryInterface(IID_IHXPreferences, (void **)&pPreferences);
- UINT32 ulTemp = 0;
- UINT32 ulConnectionBw = 10485760; /* wild guess */
- /* Get initial bandwidth guess from Prefs */
- if ((HXR_OK == ReadPrefINT32(pPreferences, "Bandwidth", ulTemp)) &&
- (ulTemp > 0))
- {
- ulConnectionBw = ulTemp;
- }
- /*
- * m_ulSustainableBitRate refers to the max bitrate that we believe is
- * sustainable over the connection. The client should never ask
- * the server to send bits faster than this rate because it could
- * cause congestion collapse.
- *
- * m_ulSelectionBitRate refers to the highest bitrate stream that we'll
- * ever try to play. Note that people can choose to pick values
- * where m_ulSelectionBitRate > m_ulSustainableBitRate. This may
- * cause rebuffers because the delivery will be capped at
- * m_ulSustainableBitRate. Why would someone do that? They may accept
- * rebuffers if it means they get a higher quality presentation.
- */
-
- /* See if we have a sustainable bandwidth factor */
- if (HXR_OK == ReadPrefINT32(pPreferences, "SustainableBwFactor",
- ulTemp))
- {
- /* clamp value to 0 <= ulTemp <= 100 range */
- if (ulTemp > 100)
- {
- ulTemp = 100;
- }
-
- /* Apply factor */
- m_ulSustainableBitRate =
- (((ulConnectionBw / 100) * ulTemp) +
- (((ulConnectionBw % 100) * ulTemp) / 100));
- }
- else
- {
- m_ulSustainableBitRate = ulConnectionBw;
- }
-
- /* See if we have a selection bandwidth factor */
- if (HXR_OK == ReadPrefINT32(pPreferences, "SelectionBwFactor",
- ulTemp))
- {
- /* clamp value to 0 <= ulTemp <= 200 range */
- if (ulTemp > 200)
- {
- ulTemp = 200;
- }
-
- /* Apply factor */
- m_ulSelectionBitRate =
- (((m_ulSustainableBitRate / 100) * ulTemp) +
- (((m_ulSustainableBitRate % 100) * ulTemp) / 100));
- }
- else
- {
- m_ulSelectionBitRate = m_ulSustainableBitRate;
- }
- /* Get MaxBandwidth from Prefs */
- if (HXR_OK != ReadPrefINT32(pPreferences, "MaxBandwidth",
- m_ulMaxAccelBitRate))
- {
- /*
- * Failed to get the MaxBandwidth preference.
- * Use m_ulSelectionBitRate value instead.
- */
- m_ulMaxAccelBitRate = m_ulSelectionBitRate;
- }
- /*
- * Get preference that controls whether we report
- * "not enough bandwidth" conditions for on-demand clips
- */
- ReadPrefBOOL(pPreferences, "CheckOnDemandBw", m_bCheckOnDemandBw);
- HX_RELEASE(pPreferences);
- }
- return res;
- }
- STDMETHODIMP HXSM2::RegisterSourcesDone(THIS)
- {
- CHXSimpleList::Iterator i;
- ASMSourceInfo2* pASMSourceInfo;
- for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
- {
- pASMSourceInfo = (ASMSourceInfo2*)(*i);
- if (pASMSourceInfo)
- {
- pASMSourceInfo->LastSetDelivery() = 0;
- }
- }
-
- m_ulOfferToRecalc = m_ulSelectionBitRate;
- if (m_ulOfferToRecalc > m_ulMaxAccelBitRate)
- {
- m_ulOfferToRecalc = m_ulMaxAccelBitRate;
- }
- Recalc();
- return HXR_OK;
- }
-
- STDMETHODIMP_(BOOL) HXSM2::NotEnoughBandwidth(THIS)
- {
- CHXSimpleList::Iterator i;
- ASMSourceInfo2* pASMSourceInfo;
- UINT32 ulTotal = 0;
- BOOL bCheckTotal = m_bCheckOnDemandBw;
- for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
- {
- pASMSourceInfo = (ASMSourceInfo2*)(*i);
- ulTotal += pASMSourceInfo->SubscribeBw();
- if (pASMSourceInfo->IsLive())
- {
- bCheckTotal = TRUE;
- }
- }
- if (bCheckTotal && ulTotal > m_ulSelectionBitRate)
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
- STDMETHODIMP HXSM2::UnRegisterSource(THIS_
- HXSource* pSource)
- {
- LISTPOSITION lPos;
- ASMSourceInfo2* pASMSourceInfo = 0;
- BOOL bFound = FALSE;
- lPos = m_pASMSourceInfo->GetHeadPosition();
- while (lPos)
- {
- pASMSourceInfo = (ASMSourceInfo2*)m_pASMSourceInfo->GetAt(lPos);
- if (pASMSourceInfo->IsMySource(pSource))
- {
- m_pASMSourceInfo->RemoveAt(lPos);
- pASMSourceInfo->Done();
- bFound = TRUE;
- break;
- }
- m_pASMSourceInfo->GetNext(lPos);
- }
-
- if (bFound)
- {
- m_ulNumStreams -= pASMSourceInfo->StreamCount();
- delete pASMSourceInfo;
- m_ulNumSources--;
-
- if (m_ulNumSources > 0)
- {
- Recalc();
- }
- }
- return HXR_OK;
- }
- STDMETHODIMP HXSM2::ChangeAccelerationStatus(THIS_
- HXSource* pSource,
- BOOL bMayBeAccelerated,
- BOOL bUseAccelerationFactor,
- UINT32 ulAccelerationFactor)
- {
- return HXR_OK;
- }
- /* Called by HXPlayer at end of each presentation */
- STDMETHODIMP HXSM2::PresentationDone(THIS)
- {
- return HXR_OK;
- }
-
- STDMETHODIMP HXSM2::ChangeBW(THIS_
- UINT32 newBW, HXSource* pSource)
- {
- return HXR_OK;
- }
- void
- HXSM2::Recalc()
- {
- CHXSimpleList::Iterator i;
- ASMStreamInfoItr streamItr(m_pASMSourceInfo);
- ASMSourceInfo2* pASMSourceInfo;
- ASMStreamInfo2* pASMStreamInfo;
- INT32 lAggregateBandwidthUsage = 0;
- UINT32 ulSourceCount;
- UINT32 ulStreamCount;
- float fBiasMean = (float) 0.;
- ulSourceCount = m_pASMSourceInfo->GetCount();
- ulStreamCount = m_ulNumStreams;
- for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
- {
- pASMSourceInfo = (ASMSourceInfo2*)(*i);
- /* Init these for later */
- pASMSourceInfo->MasterOffer() = 0;
- }
- lAggregateBandwidthUsage = m_ulOfferToRecalc;
- INT32 lCorrectAggregateBandwidthUsage = lAggregateBandwidthUsage;
- /*
- * For each stream that is at a fixed bitrate, remove that bitrate
- * from our available bandwidth.
- */
- for (streamItr.Reset(); streamItr.More(); streamItr.Next())
- {
- INT32 lBias;
- pASMStreamInfo = streamItr.Stream();
- HX_VERIFY(HXR_OK == pASMStreamInfo->GetBiasFactor(lBias));
- fBiasMean += lBias;
- if (pASMStreamInfo->IsFixedBw())
- {
- lAggregateBandwidthUsage -= pASMStreamInfo->CurrentBw();
- ulStreamCount--;
- }
- /* Init this for later */
- pASMStreamInfo->SetStreamOffer(0);
- }
- if (ulStreamCount != 0)
- {
- /* At least 1 stream is not fixed bandwidth */
- fBiasMean /= ulStreamCount;
-
- /*
- * Calculate the offer for each source that has a master rulebook
- * defining it's bandwidth division.
- */
- INT32 lNewAggregateBandwidthUsage = lAggregateBandwidthUsage;
- for (streamItr.Reset(); streamItr.More(); streamItr.Next())
- {
- INT32 lBias;
-
- pASMStreamInfo = streamItr.Stream();
- pASMSourceInfo = streamItr.Source();
-
- HX_VERIFY(HXR_OK == pASMStreamInfo->GetBiasFactor(lBias));
-
- if (pASMSourceInfo->HasMasterRuleBook())
- {
- UINT32 ulOffer =
- (UINT32)(lAggregateBandwidthUsage / ulStreamCount);
-
- ulOffer +=
- (UINT32)(((float)lBias - fBiasMean) *
- ((float)lAggregateBandwidthUsage / 100.0) *
- (2.0 / ulStreamCount));
-
- pASMSourceInfo->MasterOffer() += ulOffer;
- lNewAggregateBandwidthUsage -= ulOffer;
- }
- }
- lAggregateBandwidthUsage = lNewAggregateBandwidthUsage;
- }
- /*
- * For each source that has a master rule book, evaluate it to find
- * out how much to distribute to each stream.
- */
- for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
- {
- pASMSourceInfo = (ASMSourceInfo2*)(*i);
- if (pASMSourceInfo->HasMasterRuleBook())
- {
- pASMSourceInfo->DistributeBw();
- }
- }
- /*
- * Now go through each of the streams that are not at a
- * fixed bitrate and try to distribute the rest of the bandwidth.
- */
- UINT32 ulTakenBandwidth = 0;
- for (streamItr.Reset(); streamItr.More(); streamItr.Next())
- {
- pASMStreamInfo = streamItr.Stream();
- if (!pASMStreamInfo->IsFixedBw())
- {
- INT32 lBias;
-
- HX_VERIFY(HXR_OK == pASMStreamInfo->GetBiasFactor(lBias));
-
- UINT32 ulAltOffer =
- (UINT32)(lAggregateBandwidthUsage / (float)ulStreamCount);
- ulAltOffer += (UINT32)(((float)lBias - fBiasMean) *
- ((float)lAggregateBandwidthUsage / 100.0) *
- (2.0 / (float)ulStreamCount));
- pASMStreamInfo->SelectBw(streamItr.Source()->IsPerfectPlay(),
- ulAltOffer);
- }
- ulTakenBandwidth += pASMStreamInfo->CurrentBw();
- }
- lAggregateBandwidthUsage = lCorrectAggregateBandwidthUsage;
- BOOL bDone = FALSE;
- while (!bDone && (lAggregateBandwidthUsage < (INT32)ulTakenBandwidth))
- {
- /* Resistance is Futile. You will be Real(tm)lyAssimilated */
- UINT32 ulLowestResistance = 0xffffffff;
- ASMStreamInfo2* pLowestResistanceStream = 0;
- // Find the stream with the lowest resistence
- for (streamItr.Reset(); streamItr.More(); streamItr.Next())
- {
- pASMStreamInfo = streamItr.Stream();
- if (pASMStreamInfo->ResistanceToLower() < ulLowestResistance)
- {
- ulLowestResistance = pASMStreamInfo->ResistanceToLower();
- pLowestResistanceStream = pASMStreamInfo;
- }
- }
- if (ulLowestResistance == 0xffffffff)
- {
- bDone = TRUE;
- }
- else
- {
- ulTakenBandwidth -= (UINT32)
- pLowestResistanceStream->CurrentBw();
- pLowestResistanceStream->SelectNextLowerBw();
- ulTakenBandwidth += (UINT32)
- pLowestResistanceStream->CurrentBw();
- }
- }
- UINT32 ulLeftOverForDropByN = lAggregateBandwidthUsage - ulTakenBandwidth;
- BOOL bForce = FALSE;
- for (streamItr.Reset(); streamItr.More(); streamItr.Next())
- {
- pASMStreamInfo = streamItr.Stream();
- UINT32 ulBw = pASMStreamInfo->CurrentBw();
- if (ulBw == 1)
- {
- // Hack Alert for DropByN. XXXSMP
- ulBw = ulLeftOverForDropByN;
- }
- if ((ulBw != pASMStreamInfo->GetLastBw()) &&
- (pASMStreamInfo->IsFixedBw()))
- {
- bForce = TRUE;
- }
-
- CHXSimpleList* pSubsChanges =
- streamItr.Source()->SubsChanges();
- pASMStreamInfo->SubscribeToNewBw(ulBw, pSubsChanges);
- }
- for (i = m_pASMSourceInfo->Begin(); i != m_pASMSourceInfo->End(); ++i)
- {
- pASMSourceInfo = (ASMSourceInfo2*)(*i);
- pASMSourceInfo->SubscribeToChanges();
- pASMSourceInfo->SetDeliveryBw(m_ulSustainableBitRate);
- }
- }