buffmgr.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:20k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hlxclib/stdio.h"
  36. #include "hxcom.h"
  37. #include "hxcomm.h"
  38. #include "ihxpckts.h"
  39. #include "hxslist.h"
  40. #include "hxtick.h"
  41. #include "hxcore.h"
  42. #include "chxeven.h"
  43. #include "hxbsrc.h"
  44. #include "hxsrc.h"
  45. #include "hxntsrc.h"
  46. #include "hxstrm.h"
  47. #include "strminfo.h"
  48. #include "buffmgr.h"
  49. #include "hxsmbw.h"
  50. #include "hxgroup.h"
  51. #include "hxplay.h"
  52. #include "errdbg.h"
  53. #include "hxheap.h"
  54. #ifdef _DEBUG
  55. #undef HX_THIS_FILE
  56. static const char HX_THIS_FILE[] = __FILE__;
  57. #endif
  58. #if defined(__TCS__)
  59. #define MAX_ADDITIONAL_BUFFERING    3000
  60. #else
  61. #define MAX_ADDITIONAL_BUFFERING    10000
  62. #endif /* __TCS__ */
  63. CBufferManager::CBufferManager(HXSource* pParent)
  64. {
  65.     m_ulMaxAdditionalBufferingInMs  = MAX_ADDITIONAL_BUFFERING;
  66.     m_llHighestTimeStamp = 0;
  67.     m_ulTotalPauseTime = 0;
  68.     m_ulLastPauseTime = 0;
  69.     m_ulAdditionalBufferingInMs = 0;
  70.     m_bBufferStartTimeToBeSet = TRUE;
  71.     m_ulMinimumInitialAudioPreroll = 0;
  72.     m_ulMinimumSourcePreroll = 0;
  73.     m_bPerfectPlay = FALSE;     
  74.     m_bPaused = FALSE;
  75.     m_state = BUFFMGR_READY;
  76.     m_pParent = pParent;
  77.     m_pParent->AddRef();
  78.     m_bLocalPlayback = pParent->IsLocalSource();
  79.     m_pStreamInfoTable = pParent->GetStreamInfoTable();
  80.     m_bFirstResumeDone = FALSE;
  81.     m_bIsSeekPerformed = FALSE;
  82.     m_bBufferedPlay = FALSE;
  83.     m_bBufferCalcToBeChanged = FALSE;
  84.     m_bIsInitialized = FALSE;
  85.     m_ulSeekTime = 0;
  86. }
  87. CBufferManager::~CBufferManager()
  88. {
  89.     HX_RELEASE(m_pParent);
  90. }
  91. HX_RESULT
  92. CBufferManager::Init()
  93. {
  94.     UINT32     ulPerfectPlayTime = 0;
  95.     UINT32     ulMinimumPreroll = 0;
  96.     STREAM_INFO*    pStreamInfo = NULL;
  97.     CHXMapLongToObj::Iterator i;
  98.     // There is no buffered or perfect play with MIN_HEAP on.
  99. #if !defined(HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
  100.     SetPerfectPlay(m_pParent->IsPerfectPlay());
  101.     if (m_bPerfectPlay || m_bBufferedPlay)
  102.     {
  103. // caculate how much extra preroll for the perfect play
  104. ulPerfectPlayTime = m_pParent->GetPerfectPlayTime();
  105.     }
  106. #endif
  107.     // ajust buffering information of each stream
  108.     for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
  109.     {
  110. pStreamInfo = (STREAM_INFO*) (*i);
  111. pStreamInfo->BufferingState().Init(ulPerfectPlayTime);
  112. HX_ASSERT(pStreamInfo->m_EventList.GetHeadPosition() == NULL);
  113.     }
  114.     m_bIsInitialized = TRUE;
  115.     /* Was there a Seek called before Initialization... may happen for a clip
  116.      * with Start time
  117.      */
  118.     if (m_bIsSeekPerformed)
  119.     {
  120. DoSeek(m_ulSeekTime);
  121.     }
  122.     return HXR_OK;
  123. }
  124. HX_RESULT
  125. CBufferManager::SetMinimumPreroll(BOOL bPerfectPlay, UINT32 ulSourcePreroll, 
  126.   UINT32 ulInitialAudioPreroll,
  127.   BOOL  bModifyStartTime /* = TRUE */)
  128. {
  129.     m_ulMinimumInitialAudioPreroll = ulInitialAudioPreroll;
  130.     m_ulMinimumSourcePreroll    = ulSourcePreroll;
  131.     SetPerfectPlay(bPerfectPlay);
  132.     UpdateMinimumPreroll(bModifyStartTime);
  133.     return HXR_OK;
  134. }
  135. void 
  136. CBufferManager::UpdateMinimumPreroll(BOOL bModifyStartTime)
  137. {
  138.     UINT32     ulMinimumPreroll = 0;
  139.     UINT32     ulPerfectPlayTime = 0;
  140.     UINT32     ulStartTime = 0;
  141.     UINT32     ulEventStartTime = 0;
  142.     UINT32     ulPacketTime     = 0;
  143.     STREAM_INFO*    pStreamInfo = NULL;
  144.     BOOL     bPreDataToBeCalculated = FALSE;
  145.     CHXMapLongToObj::Iterator i;
  146.     // There is no buffered or perfect play with MIN_HEAP on.
  147. #if !defined(HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
  148.     if (m_bPerfectPlay || m_bBufferedPlay)
  149.     {
  150. m_ulMaxAdditionalBufferingInMs = 0;
  151. // caculate how much extra preroll for the perfect play
  152. ulPerfectPlayTime = m_pParent->GetPerfectPlayTime();
  153.     }
  154.     else
  155.     {
  156. m_ulMaxAdditionalBufferingInMs = MAX_ADDITIONAL_BUFFERING;
  157. if (m_ulAdditionalBufferingInMs > m_ulMaxAdditionalBufferingInMs)
  158. {
  159.     m_ulAdditionalBufferingInMs = m_ulMaxAdditionalBufferingInMs;
  160. }
  161. ulPerfectPlayTime = m_ulAdditionalBufferingInMs;
  162.     }
  163. #endif
  164.     ulStartTime = m_pParent->GetStartTime();
  165.     // adjust buffering information of each stream
  166.     for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
  167.     {
  168. pStreamInfo = (STREAM_INFO*) (*i);
  169.     
  170. pStreamInfo->BufferingState().SetMinimumPreroll(
  171.     m_ulMinimumSourcePreroll, 
  172.     m_ulMinimumInitialAudioPreroll,
  173.     ulPerfectPlayTime,
  174.     (m_state == BUFFMGR_REBUFFER));
  175. if (bModifyStartTime)
  176. {
  177.     pStreamInfo->UpdateStartTimes(ulStartTime);
  178. }
  179.     }
  180.     m_bBufferCalcToBeChanged = FALSE;
  181. }
  182. HX_RESULT
  183. CBufferManager::Stop(void)
  184. {
  185.     STREAM_INFO*    pStreamInfo = NULL;
  186.     CHXMapLongToObj::Iterator i;
  187.     // stop buffering of each stream
  188.     for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
  189.     {
  190. pStreamInfo = (STREAM_INFO*) (*i);
  191.     
  192. pStreamInfo->BufferingState().Stop();
  193. // DEBUG_OUT(m_pParent->m_pPlayer, (s,
  194. //     "BufferManager::Stop %p", pStreamInfo));
  195.     }
  196.     return HXR_OK;
  197. }
  198. HX_RESULT
  199. CBufferManager::DoSeek(UINT32 ulSeekTime, BOOL bSeekInsideRecordBuffer)
  200. {
  201.     m_state = BUFFMGR_SEEK;
  202.     m_bIsSeekPerformed = TRUE;
  203.     m_ulSeekTime = ulSeekTime;
  204.     /* We will call Reset during Init() call */
  205.     if (!m_bIsInitialized)
  206.     {
  207. return HXR_OK;
  208.     }
  209.     // reset all the preroll attributes
  210.     Reset(ulSeekTime, bSeekInsideRecordBuffer);
  211.     return HXR_OK;
  212. }
  213. HX_RESULT
  214. CBufferManager::DoPause(void)
  215. {
  216.     m_bPaused = TRUE;
  217.     m_ulLastPauseTime = HX_GET_TICKCOUNT();
  218.     return HXR_OK;
  219. }
  220. HX_RESULT
  221. CBufferManager::DoResume(void)
  222. {
  223.     if (m_bPaused && m_state != BUFFMGR_SEEK && !m_bBufferStartTimeToBeSet)
  224.     {
  225. m_ulTotalPauseTime += CALCULATE_ELAPSED_TICKS(m_ulLastPauseTime, HX_GET_TICKCOUNT());
  226.     }
  227.     m_bPaused = FALSE;
  228.     if (!m_bFirstResumeDone)
  229.     {
  230. m_bFirstResumeDone = TRUE;
  231. UpdateMinimumPreroll(FALSE);
  232.     }
  233.     return HXR_OK;
  234. }
  235. HX_RESULT
  236. CBufferManager::ReBuffer(void)
  237. {
  238.     // recaculate only if it is out of the buffering stage
  239.     // and not in perfect play mode
  240.     m_state = BUFFMGR_REBUFFER;
  241.     
  242.     /* go back in buffering mode...
  243.      * each time we come in buffering state, increase the
  244.      * number of packets we buffer by 1 second worth
  245.      * to a max of m_ulMaxAdditionalBuffering secs.
  246.      */
  247. #ifndef HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES
  248.     // increase by 1 sec
  249.     m_ulAdditionalBufferingInMs += 1000;
  250.     if (m_pParent->IsLive())
  251.     {
  252. m_bPerfectPlay = FALSE;
  253. m_bBufferedPlay = FALSE;
  254.     }
  255. #endif // HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES
  256.     UpdateMinimumPreroll(FALSE);
  257.     return HXR_OK;
  258. }
  259. HX_RESULT
  260. CBufferManager::Reset(UINT32 ulSeekTime, BOOL bSeekInsideRecordBuffer)
  261. {
  262.     STREAM_INFO*    pStreamInfo = NULL;
  263.     CHXEventList*  pEventList = NULL;
  264.     CHXEvent*     pEvent = NULL;
  265.     CHXMapLongToObj::Iterator i;
  266.     if (m_bBufferCalcToBeChanged)
  267.     {
  268. UpdateMinimumPreroll(FALSE);
  269.     }
  270.     m_ulBufferingStartTime = 0;
  271.     // reset each stream
  272.     for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
  273.     {
  274. pStreamInfo = (STREAM_INFO*) (*i);
  275. // reset
  276. if (!bSeekInsideRecordBuffer)
  277. {
  278.     pStreamInfo->m_bSrcStreamDone = FALSE;
  279.     pStreamInfo->m_bPacketRequested = FALSE;
  280. }
  281. pStreamInfo->m_bSrcStreamFillingDone = FALSE;
  282. // Reset buffering state
  283. pStreamInfo->BufferingState().Reset((m_state == BUFFMGR_SEEK),
  284.     ulSeekTime);
  285. HX_ASSERT(m_state == BUFFMGR_SEEK);
  286. if (m_state == BUFFMGR_SEEK)
  287. {
  288.     // remove all pending packets 
  289.     pEventList = &pStreamInfo->m_EventList;
  290.     while (pEventList->GetNumEvents() > 0)
  291.     {
  292. pEvent = pEventList->RemoveHead();
  293. // Mark it as a pre-seek event and send it to the player
  294. pEvent->SetPreSeekEvent();
  295. m_pParent->EventReady(pEvent);
  296.     }
  297. }
  298.     }
  299.     m_llHighestTimeStamp = 0;
  300.     m_ulTotalPauseTime = 0;
  301.     m_bBufferStartTimeToBeSet = TRUE;
  302.     return HXR_OK;
  303. }
  304. HX_RESULT
  305. CBufferManager::UpdateCounters(IHXPacket* pPacket)
  306. {
  307.     HX_RESULT     hr = HXR_OK;
  308.     UINT32     ulStreamNum = 0;
  309.     UINT32     ulBufferSize = 0;
  310.     UINT32     ulBufferTime = 0;
  311.     UINT32     ulElapsedTime = 0;
  312.     INT64     llActualTimeStamp = 0;
  313.     IHXBuffer*     pBuffer = NULL;
  314.     STREAM_INFO*    pStreamInfo = NULL;
  315.     STREAM_INFO*    pThisStreamInfo = NULL;
  316.     UINT32     ulCurrentTime   = HX_GET_TICKCOUNT();
  317.     CHXMapLongToObj::Iterator i;
  318.    
  319.     if (!pPacket)
  320.     {
  321. return HXR_INVALID_PARAMETER;
  322.     }
  323.     if (pPacket->IsLost() &&
  324. !(pPacket->GetASMFlags() & HX_ASM_DROPPED_PKT))
  325.     {
  326. // Ignore all lost packets that aren't dropped packets
  327. return hr;
  328.     }
  329.     ulStreamNum = pPacket->GetStreamNumber();
  330.     if (!m_pStreamInfoTable->Lookup(ulStreamNum, (void*&)pStreamInfo))
  331.     {
  332. return HXR_INVALID_PARAMETER;
  333.     }
  334.     pThisStreamInfo = pStreamInfo;
  335.     pBuffer = pPacket->GetBuffer();
  336.     if (pBuffer)
  337.     {
  338. ulBufferSize = pBuffer->GetSize();
  339.     }
  340.     HX_RELEASE(pBuffer);
  341.     ulBufferTime = pPacket->GetTime();
  342.     /* Set Buffering start time for all streams */
  343.     if (m_bBufferStartTimeToBeSet)
  344.     {
  345. m_bBufferStartTimeToBeSet = FALSE;
  346. m_ulBufferingStartTime = ulCurrentTime;
  347.     }
  348.     ulElapsedTime = GetElapsedTime(ulCurrentTime);
  349.     BOOL bIsBufferedPlayMode = (m_bPerfectPlay || m_bBufferedPlay || 
  350.       (m_bLocalPlayback && !m_pParent->IsLive()));
  351.     pStreamInfo->BufferingState().OnPacket(ulBufferTime, ulBufferSize,
  352.    ulElapsedTime,
  353.    m_pParent->IsLive(),
  354.    bIsBufferedPlayMode);
  355.     llActualTimeStamp = 
  356. pStreamInfo->BufferingState().CreateINT64Timestamp(ulBufferTime);
  357.     
  358.     // time based preroll by default
  359.     UpdateHighestTimestamps(llActualTimeStamp, pStreamInfo);
  360.     INT64 llLowRefTS = pThisStreamInfo->BufferingState().LowTS();
  361.     // adjust each stream preroll based on the hightest time stamp
  362.     for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
  363.     {
  364. pStreamInfo = (STREAM_INFO*) (*i);
  365. BOOL bIsTimestampDelivery = FALSE;
  366. if (pStreamInfo->m_pStream &&
  367.     pStreamInfo->m_pStream->IsTimeStampDelivery())
  368. {
  369.     bIsTimestampDelivery = TRUE;
  370. }
  371.     
  372. pStreamInfo->BufferingState().UpdateBufferingInMs(llLowRefTS,
  373.   m_llHighestTimeStamp,
  374.   bIsBufferedPlayMode,
  375.   bIsTimestampDelivery,
  376.   ulElapsedTime);
  377.     }
  378.     return hr;
  379. }
  380. HX_RESULT
  381. CBufferManager::GetStatus(REF(UINT16)     uStatusCode,
  382.   REF(IHXBuffer*)  pStatusDesc,
  383.   REF(UINT16)     uPercentDone)
  384. {
  385.     STREAM_INFO* pStreamInfo = NULL;
  386.     CHXMapLongToObj::Iterator i;
  387.     uStatusCode = HX_STATUS_READY;
  388.     pStatusDesc = NULL;
  389.     uPercentDone = 0;
  390.     // collect from each streams
  391.     for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
  392.     {
  393. pStreamInfo = (STREAM_INFO*) (*i);
  394. uPercentDone += pStreamInfo->BufferingState().GetPercentDone(m_bIsSeekPerformed);
  395.     }
  396.     // average them
  397.     uPercentDone = uPercentDone / m_pStreamInfoTable->GetCount();
  398.     if (uPercentDone >= 100)
  399.     {
  400. uPercentDone = 100;
  401. m_state = BUFFMGR_READY;
  402.     }
  403.     else
  404.     {
  405. uStatusCode = HX_STATUS_BUFFERING;
  406.     }
  407. //    DEBUG_OUT(m_pParent->m_pPlayer, DOL_GENERIC, (s,
  408. // "BuffMgr::GetStatus: %p Status: %s uPercentDone: %lu ", this, 
  409. // (uStatusCode == HX_STATUS_BUFFERING ? "HX_STATUS_BUFFERING" : "HX_STATUS_READY" ),
  410. //     uPercentDone));
  411.     return HXR_OK;
  412. }
  413. HX_RESULT
  414. CBufferManager::GetRemainToBuffer(REF(UINT32) ulRemainToBufferInMs,
  415.   REF(UINT32) ulRemainToBuffer)
  416. {
  417.     STREAM_INFO*    pStreamInfo = NULL;
  418.     
  419.     ulRemainToBufferInMs = 0;
  420.     ulRemainToBuffer = 0;
  421.     CHXMapLongToObj::Iterator i;
  422.     // caculate each stream
  423.     for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
  424.     {
  425. pStreamInfo = (STREAM_INFO*) (*i);
  426. BOOL bHasPreroll = 
  427.     pStreamInfo->BufferingState().HasPreroll(m_bIsSeekPerformed);
  428. BOOL bHasPredata =
  429.     pStreamInfo->BufferingState().HasPredata(m_bIsSeekPerformed);
  430. UINT32 ulRemainInMs;
  431. UINT32 ulRemain;
  432. pStreamInfo->BufferingState().GetRemainToBuffer(ulRemainInMs, 
  433. ulRemain);
  434. // satisfy the preroll (by default + pre-set)
  435. if ((!bHasPredata || bHasPreroll) &&
  436.     (ulRemainToBufferInMs < ulRemainInMs))
  437. {
  438.     ulRemainToBufferInMs = ulRemainInMs;
  439. }
  440. // satisfy the predata
  441. if (bHasPredata)
  442. {
  443.     ulRemainToBuffer += ulRemain;
  444. }
  445.     }
  446.     return HXR_OK;
  447. }
  448. HX_RESULT
  449. CBufferManager::GetMaximumPreroll(REF(UINT32) ulMaximumPrerollInMs)
  450. {
  451.     STREAM_INFO*    pStreamInfo = NULL;
  452.     CHXMapLongToObj::Iterator i;
  453.     ulMaximumPrerollInMs = 0;
  454.     // get max. preroll among the streams
  455.     for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
  456.     {
  457. pStreamInfo = (STREAM_INFO*) (*i);
  458.     
  459. UINT32 ulMinPrerollInMs = 
  460.     pStreamInfo->BufferingState().GetMinPrerollInMs();
  461. if (ulMaximumPrerollInMs < ulMinPrerollInMs)
  462. {
  463.     ulMaximumPrerollInMs = ulMinPrerollInMs;
  464. }
  465.     }
  466.     
  467.     return HXR_OK;
  468. }
  469. HX_RESULT
  470. CBufferManager::GetExcessBufferInfo(REF(UINT32) ulRemainToBufferInMs,
  471.   REF(UINT32) ulRemainToBuffer,
  472.   REF(UINT32) ulExcessBufferInMs,
  473.   REF(UINT32) ulExcessBuffer,
  474.   REF(BOOL) bValidInfo,
  475.   REF(UINT32) ulActualExcessBufferInMs,
  476.   REF(UINT32)   ulActualExcessBuffer)
  477. {
  478.     STREAM_INFO*    pStreamInfo = NULL;
  479.     INT64     llTheLowestTS = 0;
  480.     INT64     llTheHighestTS = 0;
  481.     BOOL     bIsFirst = TRUE;
  482.     STREAM_INFO*    pNonEmptyStreamInfo = NULL;
  483.     
  484.     ulRemainToBufferInMs    = 0;
  485.     ulRemainToBuffer     = 0;
  486.     ulExcessBufferInMs     = 0;
  487.     ulExcessBuffer     = 0;
  488.     bValidInfo     = FALSE;
  489.     ulActualExcessBufferInMs= 0;
  490.     ulActualExcessBuffer    = 0;
  491.     CHXMapLongToObj::Iterator i;
  492.     /*
  493.      * - Update transport stats for each stream.
  494.      * - Find the lowest and highest timestamps across all streams
  495.      * - Keep track of the stream with the lowest timestamp and is 
  496.      *   buffering data
  497.      */
  498.     for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
  499.     {
  500. pStreamInfo = (STREAM_INFO*) (*i);
  501. INT64 llLowestTimestampAtTransport = 0;
  502. INT64 llHighestTimestampAtTransport = 0;
  503. ULONG32 ulNumBytesAtTransport = 0;
  504. BOOL bDoneAtTransport = FALSE;
  505. m_pParent->GetCurrentBuffering(pStreamInfo->m_uStreamNumber, 
  506.        llLowestTimestampAtTransport,
  507.        llHighestTimestampAtTransport,
  508.        ulNumBytesAtTransport,
  509.        bDoneAtTransport);
  510. pStreamInfo->BufferingState().UpdateTransportStats(
  511.     llLowestTimestampAtTransport,
  512.     llHighestTimestampAtTransport,
  513.     ulNumBytesAtTransport,
  514.     bDoneAtTransport);
  515. if (ulNumBytesAtTransport > 0)
  516. {     
  517.     if (bIsFirst)
  518.     {
  519. bIsFirst     = FALSE;
  520. llTheLowestTS     = llLowestTimestampAtTransport;
  521. llTheHighestTS     = llHighestTimestampAtTransport;
  522. pNonEmptyStreamInfo = pStreamInfo;
  523.     }
  524.     else 
  525.     {
  526. if (llTheLowestTS > llLowestTimestampAtTransport)
  527. {
  528.     llTheLowestTS = llLowestTimestampAtTransport;
  529.     /* This is the stream with the lowest timestamp */
  530.     pNonEmptyStreamInfo = pStreamInfo;
  531. }
  532. if (llTheHighestTS < llHighestTimestampAtTransport)
  533. {
  534.     llTheHighestTS = llHighestTimestampAtTransport;
  535. }
  536.     }
  537. }
  538.     }
  539.     /* If none of the streams have any data buffered at the transport layer,
  540.      * return.
  541.      */
  542.     if (!pNonEmptyStreamInfo)
  543.     {
  544. return HXR_OK;
  545.     }
  546.     for (i = m_pStreamInfoTable->Begin(); i != m_pStreamInfoTable->End(); ++i)
  547.     {
  548. pStreamInfo = (STREAM_INFO*) (*i);
  549. UINT32 ulExcessForThisStreamInMs = 0;
  550. UINT32 ulExcessForThisStream     = 0;
  551. pStreamInfo->BufferingState().GetExcessBufferInfo(llTheLowestTS,
  552.   llTheHighestTS,
  553.   m_bIsSeekPerformed,
  554.   ulRemainToBufferInMs,
  555.   ulRemainToBuffer,
  556.   ulExcessBufferInMs,
  557.   ulExcessBuffer,
  558.   ulExcessForThisStreamInMs,
  559.   ulExcessForThisStream);
  560. /* Update Actual Values Regardless of Preroll / PreData */
  561. ulActualExcessBuffer += ulExcessForThisStream;
  562. if (ulActualExcessBufferInMs < ulExcessForThisStreamInMs)
  563. {
  564.     ulActualExcessBufferInMs = ulExcessForThisStreamInMs;
  565. }
  566.     }
  567.     bValidInfo = TRUE;
  568.     if (ulRemainToBufferInMs >= ulExcessBufferInMs)
  569.     {
  570. ulRemainToBufferInMs -= ulExcessBufferInMs;
  571. ulExcessBufferInMs    = 0;
  572.     }
  573.     else 
  574.     {
  575. ulExcessBufferInMs -= ulRemainToBufferInMs;
  576. ulRemainToBufferInMs  = 0;
  577.     }
  578.     if (ulRemainToBuffer > 0)
  579.     {
  580. ulExcessBuffer    = 0;
  581.     }
  582.     return HXR_OK;
  583. }
  584. void
  585. CBufferManager::EnterBufferedPlay(void)
  586. {
  587. #if !defined(HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
  588.     if (!m_bBufferedPlay && !m_bPerfectPlay)
  589.     {
  590. m_bBufferedPlay     = TRUE;
  591. UINT32 ulRemainToBufferInMs = 0;
  592. UINT32 ulRemainToBuffer = 0;
  593. GetRemainToBuffer(ulRemainToBufferInMs, ulRemainToBuffer);
  594. /* If we are not done with buffering yet, update the buffering 
  595.  * calc now!
  596.  */ 
  597. if (ulRemainToBufferInMs > 0 ||
  598.     ulRemainToBuffer > 0)
  599. {
  600.     UpdateMinimumPreroll(FALSE);
  601. }
  602. else
  603. {
  604.     m_bBufferCalcToBeChanged    = TRUE;
  605. }
  606.     }
  607. #endif // (HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
  608. }
  609. void
  610. CBufferManager::LeaveBufferedPlay(void)
  611. {
  612. #if !defined(HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
  613.     if (m_bBufferedPlay)
  614.     {
  615. m_bBufferCalcToBeChanged    = TRUE;
  616. m_bBufferedPlay     = FALSE;
  617.     }
  618. #endif // (HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
  619. }
  620. UINT32 CBufferManager::GetElapsedTime(UINT32 ulCurrentTime)
  621. {
  622.     UINT32 ulElapsedTime =
  623. CALCULATE_ELAPSED_TICKS(m_ulBufferingStartTime, ulCurrentTime);
  624.     
  625.     if (m_ulTotalPauseTime > 0)
  626.     {
  627. HX_ASSERT(ulElapsedTime >= m_ulTotalPauseTime);
  628. ulElapsedTime = ulElapsedTime > m_ulTotalPauseTime ? 
  629. ulElapsedTime - m_ulTotalPauseTime : 0;
  630.     }
  631.     return ulElapsedTime;
  632. }
  633. void CBufferManager::UpdateHighestTimestamps(INT64 llActualTimeStamp,
  634.      STREAM_INFO* pStreamInfo)
  635. {
  636.     // we apply the highest packet time-stamp to every stream
  637.     // to solve infinite buffering
  638.     if (m_llHighestTimeStamp < llActualTimeStamp)
  639.     {
  640. m_llHighestTimeStamp = llActualTimeStamp;
  641.     }
  642. }
  643. void CBufferManager::SetPerfectPlay(BOOL bPerfectPlay)
  644. {
  645.     m_bPerfectPlay = bPerfectPlay;
  646.     if (m_pParent->IsLive())
  647.     {
  648. m_bPerfectPlay = FALSE;
  649. m_bBufferedPlay = FALSE;
  650.     }
  651. }