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

Symbian

开发平台:

Visual C++

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