⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 srcinfo.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	m_strWallClockName = (const char*)pWallClockName->GetBuffer();

	/* We shouldn't already have a wall clock! */
	HX_ASSERT(m_pWallClock == NULL);

	/*
	 * Lookup a wall clock with this name, if it's not found then
	 * we are the first one, and we should create a shared wallclock
	 * object, add it to the list, and do the standard setup.
	 */
	void* pLookupResult = NULL;
	if (!m_pPlayer->FindSharedWallClocks(m_strWallClockName,pLookupResult))
	{
	    m_pWallClock = new SharedWallClock(m_strWallClockName,
					ulStreamStartTime,
					m_pPlayer);
	}
	else
	{
	    m_pWallClock = (SharedWallClock*)pLookupResult;
	    ulStreamStartTime = m_pWallClock->ResetStartTime(ulStreamStartTime);
	}
	m_pWallClock->AddUser(this);
    }

    HX_RELEASE(pValues);
    HX_RELEASE(pWallClockName);

    return ulStreamStartTime;
}

/*
 * -- LIVE SYNC SUPPORT --
 *
 * Basic clean up support for wall clock object. Notice that after
 * calling RemoveUser, you can use the wall clock object since it
 * may get deleted... so we always reset our wall clock object
 * pointer to NULL.
 */
void
SourceInfo::DoneWithWallClock()
{
    if (m_pWallClock)
    {
	m_pWallClock->RemoveUser(this);
	m_pWallClock = NULL;
    }
}

HX_RESULT
SourceInfo::ProcessIdle(BOOL	    bIsFirst,
		        ULONG32&    ulNumStreamsToBeFilled,
		        BOOL&       bIsBuffering,
		        UINT16&     uLowestBuffering,
		        BOOL	    bPersistent)
{
    HX_RESULT		theErr		    = HXR_OK;
    CHXEvent*          pEvent              = NULL;
    HXSource*          pSource             = NULL;
    IHXPendingStatus*  pStatus             = NULL;
    RendererInfo*       pRendInfo           = NULL;
    IHXValues*         pHeader             = NULL;
    HXStream*          pStream             = NULL;
    IHXRenderer*       pRenderer           = NULL;
    STREAM_INFO*        pStreamInfo         = NULL;
    IHXPacket*         pPacket             = NULL;
    UINT16              unStatusCode        = 0;
    UINT16              unPercentDone       = 0;
    UINT32		ulPacketTime	    = 0;
    INT64		llActualPacketTime  = 0;
    INT64		llLastExpectedPacketTime = 0;
    IHXBuffer*         pStatusDesc         = NULL;
    BOOL		bAtInterrupt	    = FALSE;

    bAtInterrupt = m_pPlayer->m_pEngine->AtInterruptTime();

    if (m_bStopped)
    {
	return HXR_OK;
    }

    /* Check if a source has not been initialized. This will happen
     * ONLY when we start a new track in the mid of a presentation
     */
    if (!m_bInitialized)
    {
	/* Do not initialize source at interrupt time */
	if (bAtInterrupt)
	{
	    ScheduleProcessCallback();
	    return HXR_OK;
	}

	theErr = InitializeAndSetupRendererSites();

	if (theErr || !m_bInitialized)
	{
	    return theErr;
	}
    }

    if (m_bSeekPending)
    {
	m_bSeekPending = FALSE;
	
	Pause();
	Seek(m_ulSeekTime);
	m_pSource->DoSeek(m_ulSeekTime);
	Begin();
    }

    pSource = m_pSource;
    pStatus = m_pStatus;

    // don't start getting events till the player setup has been
    // done   
    if (!m_pPlayer->m_bInitialized  || 
	m_pPlayer->m_bSetupToBeDone || 
	m_pPlayer->m_bPostSetupToBeDone)
    {
	return HXR_OK;
    }
    
    UINT16  uIndex	= 0;
    BOOL    bHandled	= TRUE;
    llLastExpectedPacketTime = m_pSource->GetLastExpectedPacketTime();

    LISTPOSITION posRend = m_pCurrentScheduleList->GetHeadPosition();
    for (; uIndex < m_pCurrentScheduleList->GetCount(); uIndex++)
    {
	BOOL	bSentMe = TRUE;
	BOOL	bEndMe = FALSE;	
	llActualPacketTime = 0;
	
	theErr = HXR_OK;

	if (uIndex > 0)
	{
	    if (bHandled)
	    {
		posRend = m_pCurrentScheduleList->RemoveAt(posRend);
		LISTPOSITION listRet = m_pCurrentScheduleList->AddTail(pRendInfo);
                // This check is critical for catching oom errors. XXXJHHB
                if( listRet == NULL )
                {
                    return HXR_OUTOFMEMORY;
                }
	    }
	    else
	    {
		m_pCurrentScheduleList->GetNext(posRend);
	    }
	}

	bHandled = TRUE;
	pRendInfo       = (RendererInfo*) 
			m_pCurrentScheduleList->GetAt(posRend);

	pStreamInfo     = pRendInfo->m_pStreamInfo;

	if (pStreamInfo->m_bSrcInfoStreamDone)
	{
	    // SPECIAL CASE:
	    // the player received all the packets(m_bSrcStreamDone is TRUE) and 
	    // EndOfPacket() hasn't been sent to the renderer yet, 
	    // BUT the renderer still calls ReportRebufferStatus()	
	    if (!IsRebufferDone())
	    {
		bIsBuffering = TRUE;
	    }
	    else
	    {
		CheckIfDone();
	    }
	    continue;
	}

	if (bIsFirst)
	{
	    pStreamInfo->m_bSrcInfoStreamFillingDone = FALSE;
	    ulNumStreamsToBeFilled++;
	}

	BOOL bThisSourceBuffering = FALSE;

	if (!bPersistent)
	{
	    // every HXSource has to implement IID_IHXPendingStatus
	    HX_ASSERT(pStatus);
	    HX_VERIFY(HXR_OK == pStatus->GetStatus(unStatusCode, pStatusDesc,
						   unPercentDone));
	    HX_RELEASE(pStatusDesc);

	    if ((HX_STATUS_BUFFERING == unStatusCode && unPercentDone < 100) ||
		HX_STATUS_CONTACTING == unStatusCode)
	    {
		bIsBuffering            = TRUE;
		bThisSourceBuffering    = TRUE;

		if (uLowestBuffering > unPercentDone)
		{
		    uLowestBuffering = unPercentDone;
		}
	    }
	}

	/* the event times are actual ts - preroll.. so we do not
	 * need to add preroll in calculations here...
	 */	  
	 
	UINT32 ulDeliveryTime = m_pPlayer->m_ulCurrentPlayTime + 
	    			   m_pPlayer->m_ulLowestGranularity;

#ifdef _MACINTOSH
#define ADDITIONAL_PREDELIVERY_TIME	4000
 	/* on Mac we try to be even farther ahead than the timeline in
 	 * packet delivery since the callbacks are not that smooth
 	 * and if we are really close to the wire, it results in
 	 * unnecccessary re-buffers. 
 	 */ 
	ulDeliveryTime += ADDITIONAL_PREDELIVERY_TIME;
#endif
	
	if (pSource)
	{
	    pSource->FillRecordControl();
	}

	if (bPersistent || bThisSourceBuffering ||
	    (pRendInfo->m_ulLatestEventTime <= ulDeliveryTime))
	{	  
    	    theErr = pSource->GetEvent(pStreamInfo->m_uStreamNumber, pEvent);

	    if (!theErr)
	    {
		pPacket = pEvent->GetPacket();

		if (pEvent->IsPreSeekEvent())
		{
		     // associate the packet with its renderer..
		     pEvent->m_pRendererInfo   = pRendInfo;		    
		     if (!bAtInterrupt || pRendInfo->m_bInterruptSafe)
		     {
			 theErr = m_pPlayer->SendPacket(pEvent);
			 delete pEvent;
		     }
		     else
		     {
			// insert event in the common packet/event list...
			theErr = m_pPlayer->m_EventList.InsertEvent(pEvent);
                        if( theErr == HXR_OUTOFMEMORY )
                        {
                            return HXR_OUTOFMEMORY;
                        }
			pRendInfo->m_ulNumberOfPacketsQueued++;
		     }

		     continue;
		}

		if (!pPacket->IsLost())
		{
		    ulPacketTime = pPacket->GetTime();

		    llActualPacketTime = 
			pRendInfo->m_pStreamInfo->BufferingState().CreateINT64Timestamp(ulPacketTime);

		    if (m_llLatestPacketTime < llActualPacketTime)
		    {
			m_llLatestPacketTime = llActualPacketTime;
		    }

		    pRendInfo->m_ulLatestEventTime  = pEvent->GetTimeStartPos();
		    
		    if (pSource->IsLive() && pRendInfo->m_bIsFirstPacket)
		    {
			pRendInfo->m_bIsFirstPacket     = FALSE;

			/*
			 * -- LIVE SYNC SUPPORT --
			 *
			 * We used to just set the stream start time to the 
			 * timestamp of this first packet. Now we use this
			 * helper function to implement support for sharing
			 * start times for sources off of the same wall clock.
			 * See other LIVE SYNC SUPPORT comments for more 
			 * details.
			 */
			UINT32 ulLiveStart = CalculateLiveStartTime(pPacket);
			pRendInfo->m_ulStreamStartTime = ulLiveStart;
			m_ulStreamStartTime = ulLiveStart;

			UINT32  ulLowestTime = 0;
			BOOL    bAtLeastOneLowestTime = FALSE;
			UINT16  uNumLowestKnown = 0;
			CHXMapLongToObj::Iterator tmpndxRend = m_pRendererMap->Begin();

			for (;!theErr && tmpndxRend != m_pRendererMap->End();
				++tmpndxRend)
			{
			    RendererInfo* pTmpRendInfo  = (RendererInfo*)(*tmpndxRend);
			    /* Have we received the lowest packet?*/
			    if (!pTmpRendInfo->m_bIsFirstPacket)
			    {
				uNumLowestKnown++;
				if (!bAtLeastOneLowestTime)
				{
				    bAtLeastOneLowestTime = TRUE;
				    ulLowestTime = pTmpRendInfo->m_ulStreamStartTime;
				    SetLiveSyncStartTime(pSource, pTmpRendInfo, ulLowestTime);
				}
				else
				{
				    if (ulLowestTime > pTmpRendInfo->m_ulStreamStartTime)
				    {
					ulLowestTime = pTmpRendInfo->m_ulStreamStartTime;
				    }
				}
			    }
			}

			if (uNumLowestKnown > 1)
			{
			    tmpndxRend = m_pRendererMap->Begin();

			    for (;!theErr && tmpndxRend != m_pRendererMap->End();
				    ++tmpndxRend)
			    {
				RendererInfo* pTmpRendInfo      = (RendererInfo*)(*tmpndxRend);
				/* Have we received the lowest packet?*/
				if (!pTmpRendInfo->m_bIsFirstPacket)
				{
				    pTmpRendInfo->m_ulStreamStartTime = ulLowestTime;
				    SetLiveSyncStartTime(pSource, pTmpRendInfo, ulLowestTime);
				}
			    }
			}
		    }

		    if ((!pSource->IsLive() || pSource->isRestrictedLiveStream()) &&
			llActualPacketTime > llLastExpectedPacketTime)
		    {
			// XXX HP
			// work around since the rule flag of all RTSP packets are set to
			// HX_ASM_SWITCH_ON only and this could cause the stream doesn't end 
			// properly if its endtime was changed after the first resume has been 
			// sent
			// THIS WILL BE FIXED IN THE NEXT SERVER RELEASE("dial-tone")  
			if (pSource->m_bRTSPRuleFlagWorkAround)
			{
			    bSentMe = FALSE;
			    bEndMe = TRUE;
			}
			else 
			{
			    pRendInfo->m_pStream->PostEndTimePacket(pPacket, bSentMe, bEndMe);
			}
		    }
		}		    

		if (bSentMe)
		{		    
		    // clear up the post events which were not sent
		    if (pStreamInfo->m_pPostEndTimeEventList)
		    {
			while (pStreamInfo->m_pPostEndTimeEventList->GetNumEvents())
			{
			    CHXEvent* pPostEndTimeEvent = pStreamInfo->m_pPostEndTimeEventList->RemoveHead();

			    // associate the packet with its renderer..
			    pPostEndTimeEvent->m_pRendererInfo   = pRendInfo;
			    // insert event in the common packet/event list...
			    theErr = m_pPlayer->m_EventList.InsertEvent(pPostEndTimeEvent);
                            if( theErr == HXR_OUTOFMEMORY )
                            {
                                return HXR_OUTOFMEMORY;
			    }
			    pRendInfo->m_ulNumberOfPacketsQueued++;
			}
		    }

		    // associate the packet with its renderer..
		    pEvent->m_pRendererInfo   = pRendInfo;
		    // insert event in the common packet/event list...
		    theErr = m_pPlayer->m_EventList.InsertEvent(pEvent);
		    if( theErr == HXR_OUTOFMEMORY )
                    {
                        return HXR_OUTOFMEMORY;
		    }
		    pRendInfo->m_ulNumberOfPacketsQueued++;
		}
		else
		{
		    if (!pStreamInfo->m_pPostEndTimeEventList)
		    {
			pStreamInfo->m_pPostEndTimeEventList = new CHXEventList();
		    }

		    if (pStreamInfo->m_pPostEndTimeEventList)
		    {
//{FILE* f1 = ::fopen("c:\\temp\\out.txt", "a+"); ::fprintf(f1, "bSentMe is FALSE PacketTime: %lu PacketRule: %u\n", pEvent->GetPacket()->GetTime(), pEvent->GetPacket()->GetASMRuleNumber());::fclose(f1);}			
			theErr = pStreamInfo->m_pPostEndTimeEventList->InsertEvent(pEvent);
			if( theErr == HXR_OUTOFMEMORY )
			{
			    return theErr;
			}
		    }
		}
	    }
	    else
	    {
		bHandled = FALSE;
	    }

	    if (theErr && !bPersistent)
	    {
		if (!pStreamInfo->m_bSrcInfoStreamFillingDone &&
		    ulNumStreamsToBeFilled > 0)
		{
		    pStreamInfo->m_bSrcInfoStreamFillingDone = TRUE;
		    ulNumStreamsToBeFilled--;
		}
	    }
	}
	else
	{
	    if (!pStreamInfo->m_bSrcInfoStreamFillingDone &&
		ulNumStreamsToBeFilled > 0)
	    {
		pStreamInfo->m_bSrcInfoStreamFillingDone = TRUE;
		ulNumStreamsToBeFilled--;
	    }
	}

	if (theErr == HXR_BUFFERING)
	{
	    if (bPersistent)
	    {
		bIsBuffering    = TRUE;
	    }
	}
	else if (theErr == HXR_AT_END)
	{
	    if (!pStreamInfo->m_bSrcInfoStreamDone)
	    {
		if (!bAtInterrupt || pRendInfo->m_bInterruptSafe)
		{
		    pStreamInfo->m_bSrcInfoStreamDone = TRUE;

		    pStreamInfo->ResetPostEndTimeEventList();

		    if (pRendInfo->m_ulNumberOfPacketsQueued == 0 &&
			pRendInfo->m_pRenderer)
		    {			
			m_pPlayer->SendPostSeekIfNecessary(pRendInfo);
			pRendInfo->m_pRenderer->OnEndofPackets();
			pRendInfo->m_bOnEndOfPacketSent = TRUE;	
		    }

		    CheckIfDone();
		}
		else
		{
		    ScheduleProcessCallback();
		    continue;
		}
	    }
	}
	else if (theErr == HXR_NO_DATA)
	{
	    /* mask this error */
	    theErr  = HXR_OK;
	}
	if (!llActualPacketTime)
	{
	    STREAM_INFO* pStrInfo = pRendInfo->m_pStreamInfo;
	    UINT32 ulPktTime = 
		pStrInfo->BufferingState().LastPacketTimestamp();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -