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

📄 vidrend.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    if(HXR_OK == pHeader->GetPropertyULONG32("StreamVersion",
	ulStreamVersion))
    {
	UINT32 ulMajorVersion = HX_GET_MAJOR_VERSION(ulStreamVersion);
	UINT32 ulMinorVersion = HX_GET_MINOR_VERSION(ulStreamVersion);
	ULONG32 ulThisMajorVersion = 0;
	ULONG32 ulThisMinorVersion = 0;

	GetStreamVersion(ulThisMajorVersion, ulThisMinorVersion);

	if((ulMajorVersion > ulThisMajorVersion) ||
	   ((ulMinorVersion > ulThisMinorVersion) &&
	    (ulMajorVersion == ulThisMajorVersion)))
	{
	    bVersionOK = FALSE;
	}
    }

    if(bVersionOK &&
       (HXR_OK == pHeader->GetPropertyULONG32("ContentVersion",
					      ulContentVersion)))
    {
	UINT32 ulMajorVersion = HX_GET_MAJOR_VERSION(ulContentVersion);
	UINT32 ulMinorVersion = HX_GET_MINOR_VERSION(ulContentVersion);
	ULONG32 ulThisMajorVersion = 0;
	ULONG32 ulThisMinorVersion = 0;

	GetContentVersion(ulThisMajorVersion, ulThisMinorVersion);

	if((ulMajorVersion > ulThisMajorVersion) ||
	   ((ulMinorVersion > ulThisMinorVersion) &&
	    (ulMajorVersion == ulMajorVersion)))
	{
	    bVersionOK = FALSE;
	}
    }

    if(!bVersionOK)
    {
        AddToAutoUpgradeCollection(GetUpgradeMimeType(), m_pContext);

	pnr = HXR_FAIL;
    }

    return pnr;
}


/////////////////////////////////////////////////////////////////////////
//  Method:
//		IHXRenderer::OnPacket
//  Purpose:
//		Called by client engine when a packet for this renderer is
//		due.
//
STDMETHODIMP CVideoRenderer::OnPacket(IHXPacket* pPacket, LONG32 lTimeOffset)
{
    m_lTimeLineOffset = lTimeOffset;

#ifdef ENABLE_INPUT_TRACE
    if (ulInputTraceIdx < MAX_INPUT_TRACE_ENTRIES)
    {
	inputTraceArray[ulInputTraceIdx++] =
	    ComputeTimeAhead(pPacket->GetTime(), 0);
    }
#endif	// ENABLE_INPUT_TRACE

    if (m_bSchedulerStartRequested)
    {
	StartSchedulers();
    }

    BOOL bQueueRet = m_pVideoFormat->Enqueue(pPacket);
    if(bQueueRet == FALSE && m_pVideoFormat->GetLastError() == HXR_OUTOFMEMORY)
    {
        return HXR_OUTOFMEMORY;
    }

    // try to decode a frame
    if (m_PlayState == Playing)
    {
	if (!IsDecoderRunning() || NULL == m_pDecoderPump)
	{
	    BOOL bDecRet = m_pVideoFormat->DecodeFrame();
            if( bDecRet == FALSE && m_pVideoFormat->GetLastError() == HXR_OUTOFMEMORY )
            {
                return HXR_OUTOFMEMORY;
            }
	}
	else
	{
	    m_pDecoderPump->Signal();
	}
    }
    else
    {
	if (!m_bBaseTimeSet)
	{
	    m_pMutex->Lock();
	    if (m_PlayState != Playing)
	    {
		m_ulBaseTime = pPacket->GetTime();
	    }
	    m_pMutex->Unlock();
	    m_bBaseTimeSet = TRUE;
	}

	// If we are seeking, this is a pre-seek packet and there is
	// no need to decode it
	if (m_PlayState != Seeking)
	{
	    if (!IsDecoderRunning() || NULL == m_pDecoderPump)
	    {
		m_pVideoFormat->DecodeFrame();
	    }
	    else
	    {
		m_pDecoderPump->Signal();
	    }

	    if (m_PlayState == Buffering)
	    {
		if (IsBufferingComplete(pPacket))
		{
		    RequestBufferingEnd();
		}
	    }
	}
    }

    return HXR_OK;
}


/////////////////////////////////////////////////////////////////////////
//  Method:
//		IHXRenderer::OnTimeSync
//  Purpose:
//		Called by client engine to inform the renderer of the current
//		time relative to the streams synchronized time-line. The
//		renderer should use this time value to update its display or
//		render it's stream data accordingly.
//
STDMETHODIMP CVideoRenderer::OnTimeSync(ULONG32 ulTime)
{
    ULONG32 ulStreamBaseTime = HX_GET_BETTERTICKCOUNT();
    ULONG32 ulBaseTime = ulTime;
    BOOL bGoodSample = TRUE;

    if (m_bSchedulerStartRequested)
    {
	StartSchedulers();
    }

#ifdef HELIX_FEATURE_STATS
    if (((ULONG32) (ulStreamBaseTime - m_pVideoStats->GetLastSyncTime())) >=
	VIDEO_STAT_INTERVAL)
    {
	m_pVideoStats->SyncStats(ulStreamBaseTime);
    }
#endif /* HELIX_FEATURE_STATS */

#ifdef ENABLE_SYNC_TRACE
    ULONG32 ulOrigStreamBaseTime = ulStreamBaseTime;
#endif // ENABLE_SYNC_TRACE

#ifdef SYNC_SMOOTHING_OLD_SCHEME
    LONG32 lNewSyncDelta = (LONG32) (ulStreamBaseTime - m_lTrendSyncDelta - ulTime);
    m_lTrendSyncDelta += lNewSyncDelta / ((LONG32) (m_ulSyncSmoothingDepth + 1));

    ulStreamBaseTime = ulTime + m_lTrendSyncDelta;

    if (m_ulSyncSmoothingDepth < m_ulSyncGoalSmoothingDepth)
    {
	m_ulSyncSmoothingDepth++;
    }
#endif	// SYNC_SMOOTHING_OLD_SCHEME

#ifdef SYNC_PRE_SMOOTHING
    if (m_ulSyncSmoothingDepth > 0)
    {
	LONG32 lStreamBaseDelta = ((LONG32) (ulStreamBaseTime - m_ulStreamBaseTime));
	ULONG32 ulBaseDelta = ulBaseTime - m_ulBaseTime;
	BOOL bSkipSmoothing = FALSE;

	bGoodSample = ((lStreamBaseDelta <= 0) ||
		       (((ULONG32) lStreamBaseDelta) <=
		        (ulBaseDelta + (ulBaseDelta >> AUDIO_SKEW_POWER))) ||
		       (bSkipSmoothing = ((m_ulBadSeqSampleCount++) > m_ulMaxBadSeqSamples)));

	if (bSkipSmoothing)
	{
	    m_ulSyncSmoothingDepth = 0;
	    m_fTrendSyncDelta = 0.0;
	}
    }
#endif	// SYNC_PRE_SMOOTHING

    if (bGoodSample)
    {
#ifdef SYNC_SMOOTHING
	double fNewSyncDelta = (((double) ((ULONG32) (ulStreamBaseTime - ulTime))) -
			       m_fTrendSyncDelta);

	// If we have a m_fTrendSyncDelta, make sure we consider
	// m_fTrendSyncDelta wrap-around in relation to fNewSyncDelta
	if (m_ulSyncSmoothingDepth > 0)
	{
	    if (fNewSyncDelta > MAX_LONG32_AS_DOUBLE)
	    {
		fNewSyncDelta = MAX_ULONG32_AS_DOUBLE - fNewSyncDelta;
	    }
	    else if (fNewSyncDelta < MIN_LONG32_AS_DOUBLE)
	    {
		fNewSyncDelta += MAX_ULONG32_AS_DOUBLE;
	    }
	}

	if (fNewSyncDelta < 0.0)
	{
	    // We are trying to speed up: use speed up smoothing criteria
	    m_fTrendSyncDelta += (fNewSyncDelta /
				  ((m_ulSyncSmoothingDepth >= m_ulSpeedupGoalSmoothingDepth) ?
				   m_ulSpeedupGoalSmoothingDepth + 1 : m_ulSyncSmoothingDepth + 1));
	}
	else
	{
	    m_fTrendSyncDelta += fNewSyncDelta / (m_ulSyncSmoothingDepth + 1);
	}

	if (m_fTrendSyncDelta > MAX_ULONG32_AS_DOUBLE)
	{
	    m_fTrendSyncDelta -= MAX_ULONG32_AS_DOUBLE;
	}
	else if (m_fTrendSyncDelta < 0)
	{
	     m_fTrendSyncDelta += MAX_ULONG32_AS_DOUBLE;
	}

	ulStreamBaseTime = ulTime + ((ULONG32) (m_fTrendSyncDelta));

	if (m_ulSyncSmoothingDepth < m_ulSyncGoalSmoothingDepth)
	{
	    m_ulSyncSmoothingDepth++;
	}
#endif	// SYNC_SMOOTHING

	m_ulGoodSeqSampleCount++;

	m_ulStreamBaseTime = ulStreamBaseTime;
	m_ulBaseTime = ulBaseTime;
	m_ulTimeNormalizationOffset = m_ulStreamBaseTime -
				      m_ulBaseTime -
				      m_lTimeLineOffset;

	if (m_ulGoodSeqSampleCount >= MIN_GOOD_PERSISTENCE_COUNT)
	{
	    m_ulBadSeqSampleCount = 0;
	}
    }
    else
    {
	// This is a bad sample
	if (m_ulBadSeqSampleCount >= MIN_BAD_PERSISTENCE_COUNT)
	{
	    m_ulGoodSeqSampleCount = 0;
	}
    }

#ifdef ENABLE_SYNC_TRACE
    if (ulSyncTraceIdx < MAX_SYNC_TRACE_ENTRIES)
    {
	syncTraceArray[ulSyncTraceIdx][0] = m_ulBaseTime;
	syncTraceArray[ulSyncTraceIdx][1] = m_ulStreamBaseTime;
	syncTraceArray[ulSyncTraceIdx++][2] = ulOrigStreamBaseTime;
    }
#endif	// ENABLE_SYNC_TRACE

    if (m_PlayState == Playing)
    {
	if (!IsDecoderRunning())
	{
	    m_pVideoFormat->DecodeFrame();
	}

	if (m_bBufferingNeeded)
	{
	    m_pMutex->Lock();

	    if (m_PlayState == Playing)
	    {
		BeginBuffering();
	    }

	    m_pMutex->Unlock();
	}
    }
    else if ((m_PlayState == PlayStarting) ||
	     (m_PlayState == Buffering))
    {
	m_pMutex->Lock();

	m_bBaseTimeSet = TRUE;

	// Reset the offset to avoid race condition
	// with m_ulTimeNormalizationOffset setting in OnPacket()
	if (bGoodSample)
	{
	    m_ulTimeNormalizationOffset = m_ulStreamBaseTime -
					  m_ulBaseTime -
					  m_lTimeLineOffset;
	}

	if (m_PlayState == Buffering)
	{
	    EndBuffering();
	    m_PlayState = PlayStarting;
	}

	if (m_PlayState == PlayStarting)
	{
	    m_PlayState = Playing;

	    BltIfNeeded();

	    StartSchedulers();

	    if (m_pBltrPump)
	    {
		m_pBltrPump->Signal();
	    }
	}

	m_pMutex->Unlock();
    }

    return HXR_OK;
}


HX_RESULT CVideoRenderer::StartSchedulers(void)
{
    HX_RESULT retVal = HXR_OK;


#ifdef HELIX_FEATURE_VIDREND_UNTIMED_DECODE

    // When running the decoder as fast as possible, we dont want to start the scheduler, so short

    // circuit this code. Additionally, calls such as BltIfNeeded() and ScheduleCallback() (which

    // may still be called) make assumptions based on the state of our interactions with the

    // scheduler, so we satisfy them by setting a pending handle representing a nonexistant callback.

    if( m_bUntimedRendering )

    {

	m_hPendingHandle = 1;

	return HXR_OK;

    }

#endif /* HELIX_FEATURE_VIDREND_UNTIMED_DECODE */


    m_bSchedulerStartRequested = FALSE;

    DisplayMutex_Lock();

    if (ShouldKickStartScheduler())
    {
	m_bBufferingNeeded = FALSE;
	ScheduleCallback(0);
    }

    if (SUCCEEDED(retVal) && (m_pDecoderPump == NULL))
    {
	CVideoPaceMaker* pVideoPaceMaker;
	retVal = HXR_OUTOFMEMORY;

	pVideoPaceMaker = new CVideoPaceMaker;

	if (pVideoPaceMaker)
	{
	    retVal = pVideoPaceMaker->QueryInterface(
		IID_IHXPaceMaker,
		(void**) &m_pDecoderPump);

	    if (SUCCEEDED(retVal))
	    {
		pVideoPaceMaker = NULL;
		m_pDecoderPump->Start(this,
		    GetDecodePriority(),
		    DECODER_INTERVAL,
		    m_ulDecoderPacemakerId);
	    }
	}

	HX_DELETE(pVideoPaceMaker);
    }

    if (SUCCEEDED(retVal) && (m_pBltrPump == NULL) && m_bTryVideoSurface2)
    {
	CVideoPaceMaker* pVideoPaceMaker;
	retVal = HXR_OUTOFMEMORY;

	pVideoPaceMaker = new CVideoPaceMaker;

	if (pVideoPaceMaker)
	{
	    retVal = pVideoPaceMaker->QueryInterface(
		IID_IHXPaceMaker,
		(void**) &m_pBltrPump);

	    if (SUCCEEDED(retVal))
	    {
		pVideoPaceMaker = NULL;
		m_pBltrPump->Start(this,
		    DFLT_PRESENT_PRIORITY,
		    BLTR_INTERVAL,
		    m_ulBltrPacemakerId);
	    }
	}

	HX_DELETE(pVideoPaceMaker);
    }

    DisplayMutex_Unlock();

    return retVal;
}


/////////////////////////////////////////////////////////////////////////
//  Method:
//	IHXRenderer::OnPreSeek
//  Purpose:
//	Called by client engine to inform the renderer that a seek is
//	about to occur. The render is informed the last time for the
//	stream's time line before the seek, as well as the first new
//	time for the stream's time line after the seek will be completed.
//
STDMETHODIMP CVideoRenderer::OnPreSeek(ULONG32 ulOldTime, ULONG32 ulNewTime)
{
    // Change state to stop Blts
    m_pMutex->Lock();
    m_PlayState = Seeking;
    m_pMutex->Unlock();

    // Suspend the Decoder pump
    if (m_pDecoderPump)
    {
	m_pDecoderPump->Suspend(TRUE);
	m_pDecoderPump->Signal();
	m_pDecoderPump->WaitForSuspend();
    }

    // Wait for Blt in progress to complete and reset
    // packet queues
    DisplayMutex_Lock();

    m_pVideoFormat->SetStartTime(ulNewTime);
    m_pVideoFormat->Reset();
#if defined(HELIX_FEATURE_STATS)
    m_pVideoStats->ResetSequence();
#endif /* HELIX_FEATURE_STATS */

    m_bFirstSurfaceUpdate = TRUE;
    m_bFirstFrame = TRUE;
    m_bBaseTimeSet = FALSE;

    DisplayMutex_Unlock();

    return HXR_OK;
}

/////////////////////////////////////////////////////////////////////////
//  Method:
//	IHXRenderer::OnPostSeek
//  Purpose:
//	Called by client engine to inform the renderer that a seek has
//	just occured. The render is informed the last time for the
//	stream's time line before the seek, as well as the first new
//	time for the stream's time line after the seek.
//
STDMETHODIMP CVideoRenderer::OnPostSeek(ULONG32 ulOldTime, ULONG32 ulNewTime)
{
    DisplayMutex_Lock();

    // clean up the packet lists
    m_pVideoFormat->SetStartTime(ulNewTime);
    m_pVideoFormat->Reset();

#if defined(HELIX_FEATURE_STATS)
    m_pVideoStats->ResetSequence();
#endif /* HELIX_FEATURE_STATS */

    m_bFirstSurfaceUpdate = TRUE;
    m_bFirstFrame = TRUE;
    m_ulBaseTime = ulNewTime;
    m_bBaseTimeSet = TRUE;
    m_bVS2BufferUnavailableOnLastBlt = FALSE;

    if (m_pDecoderPump)

⌨️ 快捷键说明

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