📄 vidrend.cpp
字号:
{
m_pDecoderPump->Suspend(FALSE);
m_pDecoderPump->Signal();
}
if (m_bUseVideoSurface2 && m_pMISUSSite)
{
FlushVideoSurface2(m_pMISUSSite);
}
DisplayMutex_Unlock();
// PostSeek signals the proper packets are to start arriving
m_pMutex->Lock();
m_PlayState = PlayStarting;
m_pMutex->Unlock();
return HXR_OK;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXRenderer::OnPause
// Purpose:
// Called by client engine to inform the renderer that a pause has
// just occured. The render is informed the last time for the
// stream's time line before the pause.
//
STDMETHODIMP CVideoRenderer::OnPause(ULONG32 ulTime)
{
m_pMutex->Lock();
m_PlayState = Paused;
m_pMutex->Unlock();
return HXR_OK;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXRenderer::OnBegin
// Purpose:
// Called by client engine to inform the renderer that a begin or
// resume has just occured. The render is informed the first time
// for the stream's time line after the resume.
//
STDMETHODIMP CVideoRenderer::OnBegin(ULONG32 ulTime)
{
HX_RESULT retVal = HXR_OK;
m_pMutex->Lock();
m_bBufferingOccured = FALSE;
// If we are seeking, PostSeek will notify us when the play
// will be starting
if (m_PlayState != Seeking)
{
m_PlayState = PlayStarting;
}
// No need to clear the Blt Packet queue here since
// The Refresh event will always clear it and clearing
// it here would create a race condition on Blt Packet
// Queue (ring buffer) read.
// ClearBltPacketQueue();
m_ulSyncSmoothingDepth = 0;
m_ulBadSeqSampleCount = 0;
m_ulGoodSeqSampleCount = 0;
m_bIsScheduledCB = 0;
m_bVS2BufferUnavailableOnLastBlt = FALSE;
retVal = StartSchedulers();
m_pMutex->Unlock();
#ifdef HELIX_FEATURE_VIDREND_BOOSTDECODE_ON_STARTUP
if (m_pDecoderPump)
{
//m_pDecoderPump->Suspend(TRUE);
//m_pDecoderPump->WaitForSuspend(); // Wait for decoder thread to start and suspends itself
//m_pDecoderPump->Suspend(FALSE);
m_pDecoderPump->Signal(); // Kick-out decoder pump from suspension
}
#endif // HELIX_FEATURE_VIDREND_BOOSTDECODE_ON_STARTUP
return retVal;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXRenderer::OnBuffering
// Purpose:
// Called by client engine to inform the renderer that buffering
// of data is occuring. The render is informed of the reason for
// the buffering (start-up of stream, seek has occured, network
// congestion, etc.), as well as percentage complete of the
// buffering process.
//
STDMETHODIMP CVideoRenderer::OnBuffering(ULONG32 ulFlags, UINT16 unPercentComplete)
{
HX_RESULT retVal = HXR_OK;
m_pMutex->Lock();
if (m_PlayState == Buffering)
{
if (IsBufferingComplete())
{
EndBuffering();
}
}
else if (m_PlayState == Playing)
{
m_PlayState = PlayStarting;
}
m_pMutex->Unlock();
return retVal;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXRenderer::GetDisplayType
// Purpose:
// Called by client engine to ask the renderer for it's preferred
// display type. When layout information is not present, the
// renderer will be asked for it's prefered display type. Depending
// on the display type a buffer of additional information may be
// needed. This buffer could contain information about preferred
// window size.
//
STDMETHODIMP CVideoRenderer::GetDisplayType(REF(HX_DISPLAY_TYPE) ulFlags,
REF(IHXBuffer*) pBuffer)
{
ulFlags = HX_DISPLAY_WINDOW |
HX_DISPLAY_SUPPORTS_RESIZE |
HX_DISPLAY_SUPPORTS_FULLSCREEN |
HX_DISPLAY_SUPPORTS_VIDCONTROLS;
return HXR_OK;
}
/************************************************************************
* Method:
* IHXRenderer::OnEndofPackets
* Purpose:
* Called by client engine to inform the renderer that all the
* packets have been delivered. However, if the user seeks before
* EndStream() is called, renderer may start getting packets again
* and the client engine will eventually call this function again.
*/
STDMETHODIMP CVideoRenderer::OnEndofPackets(void)
{
if (m_pVideoFormat)
{
m_pVideoFormat->OnRawPacketsEnded();
}
return HXR_OK;
}
/************************************************************************
* IHXStatistics Methods
*/
/************************************************************************
* InitializeStatistics
*/
#define MAX_STAT_ENTRY_PAIRS 32
STDMETHODIMP CVideoRenderer::InitializeStatistics(UINT32 ulRegistryID)
{
BOOL bCodecNameKnown = FALSE;
char* pValue = NULL;
HX_RESULT retVal = HXR_UNEXPECTED;
m_ulRegistryID = ulRegistryID;
#if defined(HELIX_FEATURE_STATS)
if (m_pVideoStats)
{
retVal = HXR_OK;
}
if (SUCCEEDED(retVal))
{
pValue = (char*) GetCodecName();
if (pValue != NULL)
{
ReportStat(VS_CODEC_NAME, pValue);
bCodecNameKnown = TRUE;
}
}
if (SUCCEEDED(retVal))
{
pValue = (char*) GetRendererName();
if (pValue != NULL)
{
ReportStat(VS_REND_NAME, pValue);
// If Codec name is unknown, use a more generic renderer name
if (!bCodecNameKnown)
{
ReportStat(VS_CODEC_NAME, pValue);
}
}
}
if (SUCCEEDED(retVal))
{
pValue = (char*) GetCodecFourCC();
if (pValue != NULL)
{
ReportStat(VS_CODEC_4CC, pValue);
}
}
if (SUCCEEDED(retVal))
{
ReportStat(VS_CURRENT_FRAMERATE, "0.0");
ReportStat(VS_FRAMES_DISPLAYED, "100.0");
ReportStat(VS_FRAMES_DROPPED, (INT32) 0);
ReportStat(VS_FRAMES_LOST, (INT32) 0);
ReportStat(VS_SURESTREAM, "FALSE");
ReportStat(VS_IMAGE_WIDTH, (INT32) 0);
ReportStat(VS_IMAGE_HEIGHT, (INT32) 0);
}
if (SUCCEEDED(retVal))
{
InitExtraStats();
}
if (SUCCEEDED(retVal))
{
retVal = m_pVideoStats->DisplayStats(m_ulRegistryID);
}
return retVal;
#else
return HXR_NOTIMPL;
#endif /* HELIX_FEATURE_STATS */
}
/************************************************************************
* UpdateStatistics
*/
STDMETHODIMP CVideoRenderer::UpdateStatistics()
{
#if defined(HELIX_FEATURE_STATS)
HX_RESULT retVal = HXR_UNEXPECTED;
if (m_pVideoStats)
{
retVal = HXR_OK;
}
if (SUCCEEDED(retVal))
{
retVal = m_pVideoStats->DisplayStats(m_ulRegistryID);
}
return retVal;
#else
return HXR_NOTIMPL;
#endif /* HELIX_FEATURE_STATS */
}
/************************************************************************
* IHXUntimedDecoder Methods
*/
#ifdef HELIX_FEATURE_VIDREND_UNTIMED_DECODE
STDMETHODIMP_(BOOL) CVideoRenderer::IsUntimedRendering()
{
return m_bUntimedRendering;
}
STDMETHODIMP_(HX_RESULT) CVideoRenderer::SetUntimedRendering(BOOL bUntimedRendering)
{
if( m_PlayState != Stopped && m_PlayState != PlayStarting )
{
return HXR_UNEXPECTED;
}
m_bUntimedRendering = bUntimedRendering;
return HXR_OK;
}
#endif /* HELIX_FEATURE_VIDREND_UNTIMED_DECODE */
/************************************************************************
* IHXUpdateProperties Methods
*/
/************************************************************************
* UpdatePacketTimeOffset
* Call this method to update the timestamp offset of cached packets
*/
STDMETHODIMP CVideoRenderer::UpdatePacketTimeOffset(INT32 lTimeOffset)
{
m_lTimeLineOffset -= lTimeOffset;
return HXR_OK;
}
/************************************************************************
* Method:
* IHXUpdateProperties::UpdatePlayTimes
* Purpose:
* Call this method to update the playtime attributes
*/
STDMETHODIMP
CVideoRenderer::UpdatePlayTimes(IHXValues* pProps)
{
return HXR_OK;
}
/************************************************************************
* IHXRenderTimeLine Methods
*/
/************************************************************************
* GetTimeLineValue
*/
STDMETHODIMP CVideoRenderer::GetTimeLineValue(REF(UINT32) ulTime)
{
ulTime = ((ULONG32) -ComputeTimeAhead(0, 0));
if (m_PlayState != Playing)
{
return HXR_TIMELINE_SUSPENDED;
}
return HXR_OK;
}
/************************************************************************
* IHXSiteUser Methods
*/
/************************************************************************
* AttachSite
*/
STDMETHODIMP CVideoRenderer::AttachSite(IHXSite* /*IN*/ pSite)
{
if (m_pMISUSSite)
{
return HXR_UNEXPECTED;
}
m_bSiteAttached = TRUE;
m_pMISUSSite = pSite;
m_pMISUSSite->AddRef();
// for sync
IHXInterruptSafe* pIHXInterruptSafe = NULL;
if (HXR_OK == m_pMISUSSite->QueryInterface(IID_IHXInterruptSafe,
(void**)&pIHXInterruptSafe))
{
// Get the pref to use the optimized scheduler or not
BOOL bUseOptimized = TRUE;
IHXBuffer* pPrefBuffer;
if( m_pPreferences &&
m_pPreferences->ReadPref("UseOptimizedScheduler",
pPrefBuffer) == HXR_OK)
{
bUseOptimized = *(pPrefBuffer->GetBuffer()) == '1';
HX_RELEASE(pPrefBuffer);
}
if (pIHXInterruptSafe->IsInterruptSafe() && bUseOptimized)
{
HX_RELEASE(m_pOptimizedScheduler);
if (HXR_OK !=
m_pContext->QueryInterface(IID_IHXOptimizedScheduler,
(void **) &m_pOptimizedScheduler))
{
// just for good luck
m_pOptimizedScheduler = NULL;
}
}
}
HX_RELEASE(pIHXInterruptSafe);
#ifdef HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
// Get Run Configuration
// Use of VideoSurface2
if (m_pPreferences)
{
ReadPrefBOOL(m_pPreferences, "VideoBoost\\NoFlip", m_bTryVideoSurface2);
}
// Use of OS Granule Boosting
if (m_pPreferences)
{
ReadPrefBOOL(m_pPreferences, "VideoBoost\\NoOSGranuleBoost", m_bOSGranuleBoost);
m_bOSGranuleBoostVS2 = m_bOSGranuleBoost;
}
// Hardware buffer count to request from VideoSurface2
if (m_bTryVideoSurface2 && m_pPreferences)
{
ReadPrefINT32(m_pPreferences, "VideoBoost\\InitialHSCount", m_ulConfigHWBufCount);
}
#endif // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
/*
* This is the best time to set the size of the site, we
* know for example the the header has already been received
* at this point.
*
* In most display renderers, you will store size information
* in your stream header. In this example, we assume a specific
* size, but we will initialize that size here as if it had
* come from our header.
*
*/
SetupBitmapDefaults(m_pHeader, m_BitmapInfoHeader);
FormatAndSetViewFrame(m_pClipRect,
m_BitmapInfoHeader,
m_rViewRect);
m_bBitmapSet = ((m_BitmapInfoHeader.biWidth > 0) &&
(m_BitmapInfoHeader.biHeight > 0));
return HXR_OK;
}
STDMETHODIMP
CVideoRenderer::DetachSite()
{
m_bSiteAttached = FALSE;
HX_RELEASE(m_pMISUSSite);
// We're done with these...
if (m_pMISUS)
{
m_pMISUS->ReleaseSingleSiteUser();
}
HX_RELEASE(m_pMISUS);
return HXR_OK;
}
STDMETHODIMP_(BOOL)
CVideoRenderer::NeedsWindowedSites()
{
return FALSE;
};
STDMETHODIMP
CVideoRenderer::HandleEvent(HXxEvent* /*IN*/ pEvent)
{
HX_RESULT retVal = HXR_OK;
pEvent->handled = FALSE;
pEvent->result = 0;
switch (pEvent->event)
{
case HX_SURFACE_UPDATE:
m_pVSMutex->Lock();
retVal = UpdateDisplay(pEvent, TRUE);
m_pVSMutex->Unlock();
break;
#if defined(HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO)
case HX_SURFACE_MODE_CHANGE:
switch ((int) pEvent->param2)
{
case HX_VIDEOSURFACE1_RECOMMENDED:
pEvent->result = SwitchToVideoSurface1();
if (SUCCEEDED(pEvent->result))
{
pEvent->handled = TRUE;
}
break;
case HX_VIDEOSURFACE1_NOT_RECOMMENDED:
pEvent->result = SwitchToVideoSurface2();
if (SUCCEEDED(pEvent->result))
{
pEvent->handled = TRUE;
}
break;
default:
HX_ASSERT(FALSE);
break;
}
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -