hxbufstate.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:23k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: hxbufstate.cpp,v 1.5.4.4 2004/07/09 02:05:57 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hxbufstate.h"
  50. #include "hxassert.h"
  51. class HXBufferedPktInfo
  52. {
  53. public:
  54.     HXBufferedPktInfo(INT64 llTimestamp, UINT32 ulSize);
  55.     INT64 Timestamp() const { return m_llTimestamp;}
  56.     UINT32 Size() const { return m_ulSize;}
  57. private:
  58.     INT64 m_llTimestamp;
  59.     UINT32 m_ulSize;
  60. };
  61. inline
  62. HXBufferedPktInfo::HXBufferedPktInfo(INT64 llTimestamp, 
  63.      UINT32 ulSize) :
  64.     m_llTimestamp(llTimestamp),
  65.     m_ulSize(ulSize)
  66. {}
  67. HXBufferingState::HXBufferingState() :
  68.     m_ulPreroll(0)
  69.     , m_ulPredata(0)
  70.     , m_ulMinimumPrerollInMs(0)
  71.     , m_ulMinimumPreroll(0)
  72.     , m_ulMinimumBufferingInMs(0)
  73.     , m_ulMinimumBuffering(0)
  74.     , m_ulRemainingToBufferInMs(0)
  75.     , m_ulRemainingToBuffer(0)
  76.     , m_ulCurrentBufferingInMs(0)
  77.     , m_ulCurrentBuffering(0)
  78.     , m_bIsFirstPacket(TRUE)
  79.     , m_preDataAtStart(FALSE)
  80.     , m_prerollAtStart(FALSE)
  81.     , m_preDataAfterSeek(FALSE)
  82.     , m_prerollAfterSeek(FALSE)
  83.     , m_llLowestTimeStamp(0)
  84.     , m_llHighestTimeStamp(0)
  85.     , m_llLowestTimestampAtTransport(0)
  86.     , m_llHighestTimestampAtTransport(0)
  87.     , m_ulNumBytesAtTransport(0)
  88.     , m_bDoneAtTransport(FALSE)
  89.     , m_ulTSRollOver(0)
  90.     , m_ulLastPacketTimeStamp(0)
  91.     , m_ulAvgBandwidth(0)
  92.     , m_pASMProps(NULL)
  93.     , m_bCurrentTimeSet(FALSE)
  94.     , m_llCurrentPlaybackTime(0)
  95.     , m_ulBufferedData(0)
  96.     , m_ulLastTimeSync(0)
  97.     , m_llFirstLivePacketTimestamp(0)
  98.     , m_ulTimeSyncRollOver(0)
  99. {}
  100. HXBufferingState::~HXBufferingState()
  101. {
  102.     HX_RELEASE(m_pASMProps);
  103.     ClearPktInfo();
  104. }
  105. void HXBufferingState::OnStreamHeader(UINT32 ulPreroll,
  106.       UINT32 ulPredata,
  107.       BOOL preDataAtStart,
  108.       BOOL preDataAfterSeek,
  109.       BOOL prerollAtStart,
  110.       BOOL prerollAfterSeek,
  111.       ULONG32 ulAvgBitRate)
  112. {
  113.     m_ulPreroll = ulPreroll;
  114.     m_ulPredata = ulPredata;
  115.     m_preDataAtStart = preDataAtStart;
  116.     m_preDataAfterSeek = preDataAfterSeek;
  117.     m_prerollAtStart = prerollAtStart;
  118.     m_prerollAfterSeek = prerollAfterSeek;
  119.     m_ulAvgBandwidth = ulAvgBitRate;
  120. }
  121. void HXBufferingState::OnStream(IUnknown* pStream)
  122. {
  123.     HX_RELEASE(m_pASMProps);
  124.     if (pStream)
  125.     {
  126. pStream->QueryInterface(IID_IHXASMProps, (void**) &m_pASMProps);
  127.     }
  128. }
  129. void HXBufferingState::Init(ULONG32 ulPerfectPlayTime)
  130. {
  131.     SetMinPrerollInMs(m_ulPreroll, m_ulPreroll + ulPerfectPlayTime);
  132.     SetMinPreroll();
  133. }
  134. void HXBufferingState::SetMinimumPreroll(UINT32 ulSourcePreroll, 
  135.  UINT32 ulInitialAudioPreroll,
  136.  UINT32 ulPerfectPlayTime,
  137.  BOOL   bIsRebuffering)
  138. {
  139.     UINT32 ulMinimumPreroll = m_ulPreroll;
  140.     
  141.     ulMinimumPreroll += ulInitialAudioPreroll;
  142.     
  143.     if (ulMinimumPreroll < ulSourcePreroll)
  144.     {
  145. ulMinimumPreroll = ulSourcePreroll;
  146.     }
  147.     
  148.     SetMinPrerollInMs(ulMinimumPreroll, 
  149.       ulMinimumPreroll + ulPerfectPlayTime);
  150.     m_ulCurrentBufferingInMs = 0;
  151.     /* If we have received at lest one packet for this stream,
  152.      * mark the lowest timestamp to be the
  153.      * last packet timstamp to reset buffering calculations
  154.      */
  155.     if (bIsRebuffering && !m_bIsFirstPacket)
  156.     {
  157. m_bIsFirstPacket = TRUE;
  158. m_llLowestTimeStamp = 
  159.     CAST_TO_INT64 (m_ulTSRollOver) * CAST_TO_INT64 MAX_UINT32 + CAST_TO_INT64 (m_ulLastPacketTimeStamp);
  160.     }
  161.     
  162.     UpdateMinPredata();
  163. }
  164. void HXBufferingState::Stop()
  165. {
  166.     m_ulRemainingToBufferInMs = 0;
  167.     m_ulRemainingToBuffer = 0;
  168. }
  169. void HXBufferingState::Reset(BOOL bIsSeeking, UINT32 ulSeekTime)
  170. {
  171.     m_ulRemainingToBufferInMs = m_ulMinimumBufferingInMs;
  172.     m_ulRemainingToBuffer = m_ulMinimumBuffering;
  173.     m_ulCurrentBufferingInMs = 0;
  174.     m_ulCurrentBuffering = 0;
  175.     m_ulTSRollOver = 0;
  176.     m_ulLastPacketTimeStamp = 0;
  177.     m_bIsFirstPacket = TRUE;
  178.     ClearPktInfo();
  179.     m_bCurrentTimeSet = FALSE;
  180.     if (bIsSeeking)
  181.     {
  182. m_llLowestTimeStamp = CAST_TO_INT64 ulSeekTime;
  183. m_llHighestTimeStamp = CAST_TO_INT64 ulSeekTime;
  184.     }
  185. }
  186. void HXBufferingState::GetRemainToBuffer(REF(UINT32) ulRemainToBufferInMs,
  187.  REF(UINT32) ulRemainToBuffer)
  188. {
  189.     ulRemainToBufferInMs = m_ulRemainingToBufferInMs;
  190.     ulRemainToBuffer = m_ulRemainingToBuffer;
  191. }
  192. UINT16 HXBufferingState::GetPercentDone(BOOL bIsSeekPerformed)
  193. {
  194.     UINT16  uTotalPercentDone = 100;
  195.     UINT16  uPreDataPercentDone = 100;
  196.     UINT16  uPrerollPercentDone = 100;
  197.     BOOL bHasPreroll;
  198.     BOOL bHasPredata;
  199.     BOOL bNeedsData = FALSE;
  200.     if (!bIsSeekPerformed)
  201.     {
  202. // start/rebuffer mode
  203. bHasPreroll = m_prerollAtStart;
  204. bHasPredata = m_preDataAtStart;
  205.     }
  206.     else
  207.     {
  208. // seek mode
  209. bHasPreroll = m_prerollAfterSeek;
  210. bHasPredata = m_preDataAfterSeek;
  211.     }
  212.     // satisfy the preroll (by default + pre-set)
  213.     if (!bHasPredata || bHasPreroll)
  214.     {
  215. // percent done on preroll
  216. if (m_ulMinimumBufferingInMs)
  217. {
  218.     uPrerollPercentDone =
  219. ((m_ulMinimumBufferingInMs-m_ulRemainingToBufferInMs ) * 100) /
  220. m_ulMinimumBufferingInMs;
  221. }
  222. uTotalPercentDone = uPrerollPercentDone;
  223. bNeedsData = (m_ulRemainingToBufferInMs > 0);
  224.     }
  225.     // satisfy the predata
  226.     if (bHasPredata)
  227.     {
  228. // percent done on predata
  229. if (m_ulMinimumBuffering)
  230. {
  231.     uPreDataPercentDone = 
  232. ((m_ulMinimumBuffering - m_ulRemainingToBuffer ) * 100) /
  233. m_ulMinimumBuffering;
  234. }
  235. uTotalPercentDone = uPreDataPercentDone;
  236. bNeedsData = (m_ulRemainingToBuffer > 0);
  237.     }
  238.     if (bHasPredata && bHasPreroll)
  239.     {
  240. uTotalPercentDone = (uPrerollPercentDone + uPreDataPercentDone) / 2;
  241.     }
  242.     else if ((bIsSeekPerformed) &&
  243.      (uTotalPercentDone == 100) &&
  244.      (bNeedsData))
  245.     {
  246. uTotalPercentDone = 99;
  247.     }
  248.     return uTotalPercentDone;
  249. }
  250. void HXBufferingState::UpdatePreroll(ULONG32 ulPreroll)
  251. {
  252.     UINT32 ulExtraPrerollInMs   = m_ulMinimumPrerollInMs - m_ulPreroll;
  253.     UINT32 ulExtraBufferingInMs = m_ulMinimumBufferingInMs - m_ulPreroll;
  254.     
  255.     SetPreroll(ulPreroll);
  256.     SetMinPrerollInMs(ulPreroll + ulExtraPrerollInMs,
  257.       ulPreroll + ulExtraBufferingInMs);
  258.     SetMinPreroll();
  259.     // Notice that we don't call ClearCurrentBufferingInMs()
  260.     // or ClearCurrentBuffering(). This allows us to count
  261.     // any data we have already received as part of the
  262.     // new preroll
  263.     CalcRemainingToBufferInMs();
  264.     CalcRemainingToBuffer();
  265. }
  266. INT64 HXBufferingState::CreateINT64Timestamp(UINT32 ulTime)
  267. {
  268.     return CAST_TO_INT64 (m_ulTSRollOver) * CAST_TO_INT64 MAX_UINT32 + CAST_TO_INT64 ulTime;
  269. }
  270. INT64 HXBufferingState::CreateINT64Timesync(UINT32 ulTime)
  271. {
  272.     return CAST_TO_INT64 (m_ulTimeSyncRollOver) * CAST_TO_INT64 MAX_UINT32 + CAST_TO_INT64 ulTime;
  273. }
  274. void HXBufferingState::OnPacket(UINT32 ulTimestamp, UINT32 ulPacketSize,
  275. UINT32 ulElapsedTime,
  276. BOOL bIsLive, BOOL bIsBufferedPlayMode)
  277. {
  278.     //  0xFA .. 0xFF [roll over] (0x01)
  279.     if (m_ulLastPacketTimeStamp > ulTimestamp &&
  280. ((m_ulLastPacketTimeStamp - ulTimestamp) > MAX_TIMESTAMP_GAP))
  281.     {
  282. m_ulTSRollOver++;
  283.     }
  284.     
  285.     INT64 llActualTimeStamp = CreateINT64Timestamp(ulTimestamp);
  286.     m_ulLastPacketTimeStamp = ulTimestamp;
  287.     if (m_bIsFirstPacket)
  288.     {
  289. /* Only if we are live,  store the first packet timestemp
  290.  * as the lowest timestamp. In any other case, we consider
  291.  * the lowest ts to be 0 OR the Seek time.
  292.  * This is to fix the post-seek buffering where we should not
  293.  * account any packets < seek ts towards buffering completion.
  294.  */
  295. if (bIsLive)
  296. {
  297.     m_llLowestTimeStamp = CAST_TO_INT64 ulTimestamp;
  298.             m_llFirstLivePacketTimestamp = m_llLowestTimeStamp;
  299.         }
  300. m_llHighestTimeStamp = CAST_TO_INT64 ulTimestamp;
  301. m_bIsFirstPacket = FALSE;
  302.     }
  303.     // Add this packet to our packet info statistics
  304.     AddPktInfo(llActualTimeStamp, ulPacketSize);
  305.     // data based preroll
  306.     if (DataBasedPreroll())
  307.     {
  308. m_ulCurrentBuffering += ulPacketSize;
  309.     
  310. if (bIsBufferedPlayMode)
  311. {
  312.     /* 
  313.      * We wait to have at least 1 second worth of data
  314.      * before doing any calculations. This may need some
  315.      * tweaking.
  316.      */
  317.     if ((m_ulRemainingToBuffer != 0) &&
  318. (m_ulCurrentBuffering >= m_ulAvgBandwidth / 8))
  319.     {
  320. /* 
  321.  * Highly unlikely, but may happen from a server on the 
  322.  * local machine.
  323.  */
  324. if (ulElapsedTime == 0)
  325. {
  326.     if (m_ulCurrentBuffering >= m_ulMinimumPreroll)
  327.     {
  328. m_ulRemainingToBuffer = 0;
  329.     }
  330. }
  331. else
  332. {
  333.     UINT32 ulDenom = ulElapsedTime * m_ulAvgBandwidth / 8000;
  334.     
  335.     /* Sanity check - may be 0 only when bandwidth
  336.      * is really low 
  337.      */
  338.     ulDenom = ulDenom > 0 ? ulDenom : 1;
  339.     
  340.     CalcRemainingToBuffer(ulDenom);
  341. }
  342.     }
  343. }
  344. else
  345. {
  346.     /* bIsBufferedPlayMode == FALSE */
  347.     if (m_ulRemainingToBuffer)
  348.     {
  349. CalcRemainingToBuffer();
  350.     }
  351. }
  352.     }
  353.     if (llActualTimeStamp >= m_llHighestTimeStamp)
  354.     {
  355. m_llHighestTimeStamp = llActualTimeStamp;
  356.     } 
  357. }
  358. void HXBufferingState::UpdateBufferingInMs(INT64 llRefLowTimestamp,
  359.    INT64 llHighTimestamp, 
  360.    BOOL bIsBufferedPlayMode,
  361.    BOOL bIsTimestampDelivery,
  362.    UINT32 ulElapsedTime)
  363. {
  364.     UpdateCurrentBufferingInMs(llRefLowTimestamp, llHighTimestamp);
  365.     if (bIsBufferedPlayMode)
  366.     {
  367. /* We handle time stamp delivered streams differently
  368.  * in case of BUffered/PerfectPlay. This is because
  369.  * server sends timestamp delivered stream based
  370.  * on the timestamps on the packet and pretty
  371.  * much streams in realtime. 
  372.  * So even if we are on LAN and streaming a RealText
  373.  * file, we will get packets in realtime even though
  374.  * we have enough bandwidth available
  375.  * 
  376.  * For timestamp delivered streams, we just fulfill 
  377.  * preroll.
  378.  */
  379. if (bIsTimestampDelivery &&
  380.     m_ulCurrentBufferingInMs > m_ulMinimumPrerollInMs)
  381. {
  382.     m_ulRemainingToBufferInMs = 0;
  383. }
  384. else if ((m_ulRemainingToBufferInMs != 0) &&
  385.  (m_ulCurrentBufferingInMs >= 1000))
  386. {
  387.     /* 
  388.      * Highly unlikely, but may happen from a 
  389.      * server on the local machine.
  390.      */
  391.     if (ulElapsedTime == 0)
  392.     {
  393. if (m_ulCurrentBufferingInMs >= m_ulMinimumPrerollInMs)
  394. {
  395.     m_ulRemainingToBufferInMs = 0;
  396. }
  397.     }
  398.     else
  399.     {
  400. CalcRemainingToBufferInMs(ulElapsedTime);
  401.     }
  402. }
  403.     }
  404.     else
  405.     {
  406. /* bIsBufferedPlayMode == FALSE */
  407. if (m_ulRemainingToBufferInMs)
  408. {
  409.     CalcRemainingToBufferInMs();
  410. }
  411.     }
  412. }
  413. void HXBufferingState::UpdateTransportStats(INT64 llLowTSAtTransport,
  414.     INT64 llHighTSAtTransport,
  415.     ULONG32 ulBytesAtTransport,
  416.     BOOL bDoneAtTransport)
  417. {
  418.     m_llLowestTimestampAtTransport = llLowTSAtTransport; 
  419.     m_llHighestTimestampAtTransport = llHighTSAtTransport; 
  420.     m_ulNumBytesAtTransport = ulBytesAtTransport;
  421.     m_bDoneAtTransport = bDoneAtTransport;
  422. }
  423. HX_RESULT HXBufferingState::GetBufferingStats(REF(INT64) llLowTimestamp, 
  424.       REF(INT64) llHighTimestamp,
  425.       REF(UINT32) ulBytesBuffered,
  426.       BOOL bUseTransportStats)
  427. {
  428.     HX_RESULT res = HXR_NO_DATA;
  429.     if (!m_bIsFirstPacket)
  430.     {
  431.         // Note: GetBufferedData() MUST be called first because
  432.         //       it is the one responsible for pruning the list
  433.         ulBytesBuffered = GetBufferedData();
  434. if (!m_pktInfo.IsEmpty())
  435. {
  436.     HXBufferedPktInfo* pPktInfo = 
  437. (HXBufferedPktInfo*)m_pktInfo.GetHead();
  438.     llLowTimestamp = pPktInfo->Timestamp();
  439. }
  440. else
  441. {
  442.     llLowTimestamp = m_llHighestTimeStamp;
  443. }
  444. llHighTimestamp = m_llHighestTimeStamp;
  445. if (bUseTransportStats)
  446. {
  447.     if (m_llHighestTimestampAtTransport > llHighTimestamp)
  448.     {
  449. llHighTimestamp = m_llHighestTimestampAtTransport;
  450.     }
  451.     ulBytesBuffered += m_ulNumBytesAtTransport;
  452. }
  453. res = HXR_OK;
  454.     }
  455.     return res;
  456. }
  457. void HXBufferingState::GetExcessBufferInfo(INT64 llTheLowestTS,
  458.    INT64 llTheHighestTS,
  459.    BOOL bIsSeekPerformed,
  460.    REF(UINT32) ulRemainToBufferInMs,
  461.    REF(UINT32) ulRemainToBuffer,
  462.    REF(UINT32) ulExcessBufferInMs,
  463.    REF(UINT32) ulExcessBuffer,
  464.    REF(UINT32) ulExcessForThisStreamInMs,
  465.    REF(UINT32) ulExcessForThisStream)
  466. {
  467.     UINT32 ulCurBufInMs     = 0;
  468.     UINT32 ulRemainForThisStreamInMs = 0;
  469.     UINT32 ulRemainForThisStream     = 0;
  470.     
  471.     ulExcessForThisStreamInMs = 0;
  472.     ulExcessForThisStream     = 0;
  473.     
  474.     if (m_ulNumBytesAtTransport > 0)
  475.     {
  476. HX_ASSERT((llTheHighestTS - m_llLowestTimestampAtTransport) < MAX_TIMESTAMP_GAP);
  477. ulCurBufInMs = INT64_TO_UINT32(llTheHighestTS - 
  478.        m_llLowestTimestampAtTransport);
  479.     }
  480.     else
  481.     {
  482. HX_ASSERT((llTheHighestTS - llTheLowestTS) < MAX_TIMESTAMP_GAP);
  483. ulCurBufInMs = INT64_TO_UINT32(llTheHighestTS - llTheLowestTS);
  484.     }
  485.     if (ulCurBufInMs <= m_ulMinimumBufferingInMs)
  486.     {
  487. ulRemainForThisStreamInMs = m_ulMinimumBufferingInMs - ulCurBufInMs;
  488.     }
  489.     else
  490.     {
  491. ulExcessForThisStreamInMs = ulCurBufInMs - m_ulMinimumBufferingInMs;
  492.     }
  493.     if (m_ulNumBytesAtTransport <= m_ulMinimumBuffering)
  494.     {
  495. ulRemainForThisStream = 
  496.     m_ulMinimumBuffering - m_ulNumBytesAtTransport;
  497.     }
  498.     else
  499.     {
  500. ulExcessForThisStream = m_ulNumBytesAtTransport - m_ulMinimumBuffering;
  501.     }
  502.     
  503.     BOOL bHasPreroll = HasPreroll(bIsSeekPerformed);
  504.     BOOL bHasPredata = HasPredata(bIsSeekPerformed);
  505.     // satisfy the preroll (by default + pre-set)
  506.     if (!bHasPredata || bHasPreroll)
  507.     {
  508. if (ulRemainToBufferInMs < ulRemainForThisStreamInMs)
  509. {
  510.     ulRemainToBufferInMs = ulRemainForThisStreamInMs;
  511. }
  512. if (ulExcessBufferInMs < ulExcessForThisStreamInMs)
  513. {
  514.     ulExcessBufferInMs = ulExcessForThisStreamInMs;
  515. }
  516.     }
  517.     // satisfy the predata
  518.     if (bHasPredata)
  519.     {
  520. ulRemainToBuffer += ulRemainForThisStream;
  521. ulExcessBuffer   += ulExcessForThisStream;
  522.     }
  523. }
  524. void HXBufferingState::OnTimeSync(UINT32 ulCurrentTime)
  525. {
  526.     //  0xFA .. 0xFF [roll over] (0x01)
  527.     if (m_ulLastTimeSync > ulCurrentTime &&
  528.        ((m_ulLastTimeSync - ulCurrentTime) > MAX_TIMESTAMP_GAP))
  529.     {
  530.        m_ulTimeSyncRollOver++;
  531.     }
  532.     m_ulLastTimeSync = ulCurrentTime;
  533.     m_llCurrentPlaybackTime = CreateINT64Timesync(ulCurrentTime);
  534.     // Add back the first live packet timestamp.
  535.     // If not live, then m_llFirstLivePacketTimeStamp is 0.
  536.     m_llCurrentPlaybackTime += m_llFirstLivePacketTimestamp;
  537.     m_bCurrentTimeSet = TRUE;
  538. }
  539. void HXBufferingState::SetMinPrerollInMs(ULONG32 ulMinPrerollInMs, 
  540.  ULONG32 ulMinBufferingInMs)
  541. {
  542.     m_ulMinimumPrerollInMs    = ulMinPrerollInMs;
  543.     m_ulMinimumBufferingInMs  = ulMinBufferingInMs;
  544.     m_ulRemainingToBufferInMs = m_ulMinimumBufferingInMs;
  545. }
  546. void HXBufferingState::SetMinPreroll()
  547. {
  548.     SetMinPreroll(MsToBytes(m_ulMinimumPrerollInMs,
  549.     m_ulAvgBandwidth),
  550.   m_ulAvgBandwidth);
  551. }
  552. void HXBufferingState::SetMinPreroll(UINT32 ulMinimumPredata,
  553.      UINT32 ulBandwidth)
  554. {
  555.     HX_ASSERT(m_ulMinimumPrerollInMs >= m_ulPreroll);
  556.     UINT32 ulExtraBufferingInMs = m_ulMinimumPrerollInMs - m_ulPreroll;
  557.     /* Get current bandiwidth from asm */
  558.     m_ulMinimumPreroll = (ulMinimumPredata + 
  559.    MsToBytes(ulExtraBufferingInMs, 
  560.      ulBandwidth));
  561.     // There is no buffered or perfect play with MIN_HEAP on.
  562. #if defined(HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
  563.     m_ulMinimumBuffering  = m_ulMinimumPreroll;
  564. #else
  565.     ulExtraBufferingInMs = m_ulMinimumBufferingInMs - m_ulPreroll;
  566.     m_ulMinimumBuffering  = (ulMinimumPredata + 
  567.      MsToBytes(ulExtraBufferingInMs, 
  568.        ulBandwidth));
  569. #endif
  570.     m_ulRemainingToBuffer  = m_ulMinimumBuffering;
  571.     m_ulCurrentBuffering   = 0;
  572. }
  573. void HXBufferingState::UpdateMinPredata()
  574. {
  575.     UINT32     ulMinimumPredata = m_ulPredata;
  576.     UINT32     ulBandwidth      = m_ulAvgBandwidth;
  577.     
  578. #if defined(HELIX_FEATURE_ASM)
  579.     // no ASMProps in AutoConfig
  580.     HX_ASSERT(m_pASMProps);
  581.     
  582.     if (m_pASMProps)
  583.     {
  584. UINT32 ulTmp;
  585. if (HXR_OK == m_pASMProps->GetPreData(ulTmp))
  586. {
  587.     ulMinimumPredata = ulTmp;
  588. }
  589. if (HXR_OK == m_pASMProps->GetBandwidth(ulTmp))
  590. {
  591.     ulBandwidth = ulTmp;
  592. }
  593.     }
  594. #endif /* HELIX_FEATURE_ASM */
  595.     
  596.     SetMinPreroll(ulMinimumPredata, ulBandwidth);
  597. }
  598. void HXBufferingState::UpdateCurrentBufferingInMs(INT64 llLowestTimeStamp, 
  599.   INT64 llHighestTimeStamp)
  600. {
  601.     INT64 llLowTimestamp = m_llLowestTimeStamp;
  602.     
  603.     if (m_bIsFirstPacket)
  604.     {
  605. /* use the reference stream's lowest timestamp for calculation */
  606. llLowTimestamp = llLowestTimeStamp;
  607.     }
  608.     if (llHighestTimeStamp > llLowTimestamp)
  609.     {
  610. // if the stream has been continuesly playing for 49 days
  611. // we will set m_ulCurrentBufferingInMs to MAX_UINT32
  612. if (llHighestTimeStamp - llLowTimestamp > MAX_UINT32)
  613. {
  614.     m_ulCurrentBufferingInMs = MAX_UINT32;
  615. }
  616. else
  617. {
  618.     m_ulCurrentBufferingInMs = 
  619. INT64_TO_UINT32(llHighestTimeStamp - llLowTimestamp);
  620. }
  621.     }
  622. }
  623. ULONG32 HXBufferingState::MsToBytes(ULONG32 ulValueInMs, ULONG32 ulBw) const
  624. {
  625.     return (ulValueInMs * (ulBw / 8)) / 1000;
  626. }
  627. void HXBufferingState::CalcRemainingToBufferInMs()
  628. {
  629.     m_ulRemainingToBufferInMs = CalcRemaining(m_ulMinimumBufferingInMs,
  630.       m_ulCurrentBufferingInMs,
  631.       0,
  632.       0);
  633. }
  634. void HXBufferingState::CalcRemainingToBufferInMs(ULONG32 ulElapsedTime)
  635. {
  636.     m_ulRemainingToBufferInMs = CalcRemaining(m_ulMinimumBufferingInMs,
  637.       m_ulCurrentBufferingInMs,
  638.       m_ulMinimumPrerollInMs,
  639.       ulElapsedTime);
  640. }
  641. void HXBufferingState::CalcRemainingToBuffer()
  642. {
  643.     m_ulRemainingToBuffer = CalcRemaining(m_ulMinimumBuffering,
  644.   m_ulCurrentBuffering,
  645.   0,
  646.   0);
  647. }
  648. void HXBufferingState::CalcRemainingToBuffer(ULONG32 ulDenom)
  649. {
  650.     m_ulRemainingToBuffer = CalcRemaining(m_ulMinimumBuffering,
  651.   m_ulCurrentBuffering,
  652.   m_ulMinimumPreroll,
  653.   ulDenom);
  654. }
  655. UINT32 HXBufferingState::CalcRemaining(UINT32 ulMinimumBuffering,
  656.        UINT32 ulCurrentBuffering,
  657.        UINT32 ulMinimumPreroll,
  658.        UINT32 ulDenom) const
  659. {
  660.     UINT32 ulRemainingToBuffer = 0;
  661.     if (ulMinimumBuffering > ulCurrentBuffering)
  662.     {
  663. ulRemainingToBuffer = ulMinimumBuffering - ulCurrentBuffering;
  664.     }
  665.     if (ulDenom)
  666.     {
  667. UINT32 ulBufferWhilePlaying = ulRemainingToBuffer;
  668. /*
  669.  * Buffers during playback = X*X/Y + X*(X/Y)^2 + X*(X/Y)^3 + ....
  670.  *     = X*X/Y (1 + X/Y + (X/Y)^2 + ....)
  671.  *
  672.  *      = X*X/Y ( 1 / (1 - X/Y))  IFF X/Y < 1 i.e. X < Y
  673.  *
  674.  *       ELSE We have enough data... Satisfy preroll 
  675.  */
  676. /* Add a fudge factor of 10% */
  677. ulDenom = (UINT32) (ulDenom * 1.10);
  678. if (ulCurrentBuffering < ulDenom)
  679. {
  680.     double x = ulCurrentBuffering;
  681.     double y = ulDenom;
  682.     ulBufferWhilePlaying = (UINT32) (((x * x) / y) * (1. / (1. - x / y)));
  683. }
  684. if (ulBufferWhilePlaying < ulRemainingToBuffer)
  685. {
  686.     ulRemainingToBuffer -= ulBufferWhilePlaying;
  687. }
  688. else if (ulCurrentBuffering >= ulMinimumPreroll)
  689. {
  690.     ulRemainingToBuffer = 0;
  691. }
  692.     }
  693.     return ulRemainingToBuffer;
  694. }
  695. void HXBufferingState::SetAvgBWToASMBw()
  696. {
  697.     UINT32 ulBandwidth = 0;
  698.     if (m_pASMProps &&
  699. m_pASMProps->GetBandwidth(ulBandwidth) == HXR_OK)
  700.     {
  701. m_ulAvgBandwidth = ulBandwidth;
  702.     }
  703. }
  704. void HXBufferingState::ClearPktInfo()
  705. {
  706.     m_ulBufferedData = 0;
  707.     while(!m_pktInfo.IsEmpty())
  708.     {
  709. HXBufferedPktInfo* pInfo = (HXBufferedPktInfo*)m_pktInfo.RemoveHead();
  710. delete pInfo;
  711.     }
  712. }
  713. void HXBufferingState::AddPktInfo(INT64 llTimestamp, UINT32 ulPacketSize)
  714. {
  715.     // Create the HXBufferedPktInfo class
  716.     HXBufferedPktInfo* pPktInfo = new HXBufferedPktInfo(llTimestamp, 
  717. ulPacketSize);
  718.     if (pPktInfo)
  719.     {
  720. m_pktInfo.AddTail(pPktInfo);
  721. m_ulBufferedData += ulPacketSize;
  722.     }
  723.     // purge the old packet info data
  724.     //  this keeps the list short and prevents the Symbian
  725.     //  allocator from freaking out
  726.     (void)GetBufferedData();
  727. }
  728. UINT32 HXBufferingState::GetBufferedData()
  729. {
  730.     BOOL bDone = m_pktInfo.IsEmpty() || !m_bCurrentTimeSet;
  731.     
  732.     // Remove all packet info that is past due
  733.     // and subtract their sizes from our buffering total
  734.     while(!bDone)
  735.     {
  736. HXBufferedPktInfo* pPktInfo = (HXBufferedPktInfo*)m_pktInfo.GetHead();
  737. if (pPktInfo->Timestamp() <= m_llCurrentPlaybackTime)
  738. {
  739.     m_ulBufferedData -= pPktInfo->Size();
  740.     
  741.     m_pktInfo.RemoveHead();
  742.     delete pPktInfo;
  743.     
  744.     bDone = m_pktInfo.IsEmpty();
  745. }
  746. else
  747. {
  748.     bDone = TRUE;
  749. }
  750.     }
  751.     return m_ulBufferedData;
  752. }