📄 vidrend.cpp
字号:
delete m_pActiveVideoPacket;
m_pActiveVideoPacket = NULL;
m_ulActiveVideoTime = 0;
}
HX_RELEASE(m_pHeader);
HX_RELEASE(m_pContext);
HX_RELEASE(m_pCommonClassFactory);
if (m_pVideoFormat)
{
m_pVideoFormat->Release();
m_pVideoFormat = NULL;
}
HX_DELETE(m_pVSurf2InputBIH);
HX_DELETE(m_pClipRect);
HX_DELETE(m_pMutex);
HX_DELETE(m_pBltMutex);
HX_DELETE(m_pVSMutex);
RemoveCallback(m_hPendingHandle);
m_bPendingCallback = FALSE;
HX_RELEASE(m_pOptimizedScheduler);
HX_RELEASE(m_pScheduler);
HX_RELEASE(m_pPreferences);
HX_RELEASE(m_pRegistry);
ClearBltPacketQueue();
HX_DELETE(m_pBltPacketQueue);
HX_RELEASE(m_pResizeCB);
#if defined(HELIX_FEATURE_STATS)
HX_DELETE(m_pVideoStats);
#endif /* HELIX_FEATURE_STATS */
}
/************************************************************************
* IHXPlugin Methods
*/
/************************************************************************
* Method:
* IHXPlugin::InitPlugin
* Purpose:
* Initializes the plugin for use. This interface must always be
* called before any other method is called. This is primarily needed
* so that the plugin can have access to the context for creation of
* IHXBuffers and IMalloc.
*/
STDMETHODIMP CVideoRenderer::InitPlugin(IUnknown* /*IN*/ pContext)
{
HX_RESULT retVal = HXR_OK;
HX_ASSERT(pContext);
m_pContext = pContext;
m_pContext->AddRef();
retVal = m_pContext->QueryInterface(IID_IHXCommonClassFactory,
(void**) &m_pCommonClassFactory);
if (SUCCEEDED(retVal))
{
m_pContext->QueryInterface(IID_IHXPreferences,
(void**) &m_pPreferences);
}
m_pContext->QueryInterface(IID_IHXRegistry, (void**) &m_pRegistry);
if (SUCCEEDED(retVal))
{
retVal = m_pContext->QueryInterface(IID_IHXScheduler,
(void **) &m_pScheduler);
}
if (SUCCEEDED(retVal) && !m_pMutex)
{
#ifdef THREADS_SUPPORTED
retVal = HXMutex::MakeMutex(m_pMutex);
#else // THREADS_SUPPORTED
retVal = HXMutex::MakeStubMutex(m_pMutex);
#endif // THREADS_SUPPORTED
}
if (SUCCEEDED(retVal) && !m_pBltMutex)
{
#ifdef THREADS_SUPPORTED
retVal = HXMutex::MakeMutex(m_pBltMutex);
#else // THREADS_SUPPORTED
retVal = HXMutex::MakeStubMutex(m_pBltMutex);
#endif // THREADS_SUPPORTED
}
if (SUCCEEDED(retVal) && !m_pVSMutex)
{
#ifdef THREADS_SUPPORTED
retVal = HXMutex::MakeMutex(m_pVSMutex);
#else // THREADS_SUPPORTED
retVal = HXMutex::MakeStubMutex(m_pVSMutex);
#endif // THREADS_SUPPORTED
}
#if defined(HELIX_FEATURE_STATS)
if (SUCCEEDED(retVal))
{
m_pVideoStats = new CVideoStatistics(m_pContext,
VIDEO_STAT_INTERVAL_COUNT);
retVal = HXR_OUTOFMEMORY;
if (m_pVideoStats)
{
retVal = HXR_OK;
}
}
#endif /* HELIX_FEATURE_STATS */
if (FAILED(retVal))
{
HX_RELEASE(m_pCommonClassFactory);
HX_RELEASE(m_pPreferences);
HX_RELEASE(m_pRegistry);
HX_RELEASE(m_pScheduler);
}
return retVal;
}
/************************************************************************
* Method:
* IHXPlugin::GetPluginInfo
* Purpose:
* Returns the basic information about this plugin. Including:
*
* bLoadMultiple whether or not this plugin DLL can be loaded
* multiple times. All File Formats must set
* this value to TRUE.
* pDescription which is used in about UIs (can be NULL)
* pCopyright which is used in about UIs (can be NULL)
* pMoreInfoURL which is used in about UIs (can be NULL)
*/
STDMETHODIMP CVideoRenderer::GetPluginInfo
(
REF(BOOL) /*OUT*/ bLoadMultiple,
REF(const char*) /*OUT*/ pDescription,
REF(const char*) /*OUT*/ pCopyright,
REF(const char*) /*OUT*/ pMoreInfoURL,
REF(ULONG32) /*OUT*/ ulVersionNumber
)
{
bLoadMultiple = TRUE; // Must be true for file formats.
pDescription = zm_pDescription;
pCopyright = zm_pCopyright;
pMoreInfoURL = zm_pMoreInfoURL;
ulVersionNumber = TARVER_ULONG32_VERSION;
return HXR_OK;
}
/************************************************************************
* Method:
* IHXPlugin::GetRendererInfo
* Purpose:
* If this object is a file format object this method returns
* information vital to the instantiation of file format plugins.
* If this object is not a file format object, it should return
* HXR_UNEXPECTED.
*/
STDMETHODIMP CVideoRenderer::GetRendererInfo
(
REF(const char**) /*OUT*/ pStreamMimeTypes,
REF(UINT32) /*OUT*/ unInitialGranularity
)
{
pStreamMimeTypes = (const char**) zm_pStreamMimeTypes;
unInitialGranularity = SYNC_INTERVAL;
return HXR_OK;
}
/************************************************************************
* IHXRenderer Methods
*/
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXRenderer::StartStream
// Purpose:
// Called by client engine to inform the renderer of the stream it
// will be rendering. The stream interface can provide access to
// its source or player. This method also provides access to the
// primary client controller interface.
//
STDMETHODIMP CVideoRenderer::StartStream(IHXStream* pStream,
IHXPlayer* pPlayer)
{
m_pStream = pStream;
if (m_pStream)
{
m_pStream->AddRef();
}
#if defined (HELIX_FEATURE_MISU)
m_pCommonClassFactory->CreateInstance(
CLSID_IHXMultiInstanceSiteUserSupplier,
(void**) &m_pMISUS);
if (m_pMISUS)
{
m_pMISUS->SetSingleSiteUser((IUnknown*)(IHXSiteUser*) this);
}
#endif //HELIX_FEATURE_MISU
if (m_pStream)
{
IHXStreamSource* pSource = 0;
if (m_pStream->GetSource(pSource) == HXR_OK)
{
/* It is OK if the source does not support backchannel. Reasons:
*
* 1. This stream may not be coming from h261 fileformat.
* It may instead be merged into a container fileformat which
* may be does not support BackChannel.
*
* 2. The protocol used to serve this stream may not support
* BackChannel.
*/
pSource->QueryInterface(IID_IHXBackChannel, (void**) &m_pBackChannel);
pSource->Release();
}
}
return HXR_OK;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXRenderer::EndStream
// Purpose:
// Called by client engine to inform the renderer that the stream
// is was rendering is closed.
//
STDMETHODIMP CVideoRenderer::EndStream()
{
// Stop Blts by changing state
m_pMutex->Lock();
m_PlayState = Stopped;
m_pMutex->Unlock();
// Stop Decoder
if (m_pDecoderPump)
{
m_pDecoderPump->Stop();
m_pDecoderPump->Signal();
m_pDecoderPump->WaitForStop();
m_pDecoderPump->Release();
m_pDecoderPump = NULL;
}
// Wait for Blt if in progress and then flush packet queues
DisplayMutex_Lock();
if (m_pVideoFormat)
{
m_pVideoFormat->Reset();
}
DisplayMutex_Unlock();
// IHXStream, IHXSourceStream or IHXBackChannel
// cannot be used after EndStream has been called.
HX_RELEASE(m_pStream);
HX_RELEASE(m_pBackChannel);
// Stop Bltr pump
if (m_pBltrPump)
{
m_pBltrPump->Stop();
m_pBltrPump->Signal();
}
// Flush Optimized Video Surface if used
if (m_bUseVideoSurface2 && m_pMISUSSite)
{
FlushVideoSurface2(m_pMISUSSite);
}
if (m_pBltrPump)
{
m_pBltrPump->WaitForStop();
m_pBltrPump->Release();
m_pBltrPump = NULL;
}
DisplayMutex_Lock();
if (m_pVideoFormat)
{
m_pVideoFormat->Release();
m_pVideoFormat = NULL;
}
DisplayMutex_Unlock();
#ifdef ENABLE_SYNC_TRACE
DumpSyncEntries();
#endif // ENABLE_SYNC_TRACE
#ifdef ENABLE_SCHED_TRACE
DumpSchedEntries();
#endif // ENABLE_SCHED_TRACE
#ifdef ENABLE_FETCH_TRACE
DumpFetchEntries();
#endif // ENABLE_FETCH_TRACE
#ifdef ENABLE_INPUT_TRACE
DumpInputEntries();
#endif // ENABLE_INPUT_TRACE
return HXR_OK;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXRenderer::OnHeader
// Purpose:
// Called by client engine when a header for this renderer is
// available. The header will arrive before any packets.
//
STDMETHODIMP CVideoRenderer::OnHeader(IHXValues* pHeader)
{
HX_RESULT retVal = HXR_OK;
HX_DELETE(m_pClipRect);
// Keep this for later use...
HX_RELEASE(m_pHeader);
m_pHeader = pHeader;
m_pHeader->AddRef();
m_ulStreamBaseTime = 0;
m_ulBaseTime = 0;
m_ulTimeNormalizationOffset = 0;
// check the stream versions
m_pHeader->AddRef();
retVal = CheckStreamVersions(m_pHeader);
m_pHeader->Release();
#ifdef HELIX_FEATURE_QUICKTIME
IHXBuffer* pSDPData = NULL;
if (SUCCEEDED(retVal) &&
SUCCEEDED(pHeader->GetPropertyCString("SDPData", pSDPData)))
{
char *pData = (char*) pSDPData->GetBuffer();
IHXValues *pValues = NULL;
if (pData &&
SUCCEEDED(SDPParseChunk(pData,
strlen(pData),
pValues,
m_pCommonClassFactory,
SDPCTX_Renderer)))
{
ULONG32 ulLeft;
ULONG32 ulRight;
ULONG32 ulTop;
ULONG32 ulBottom;
if (SUCCEEDED(pValues->GetPropertyULONG32(
"ClipFrameLeft", ulLeft)) &&
SUCCEEDED(pValues->GetPropertyULONG32(
"ClipFrameRight", ulRight)) &&
SUCCEEDED(pValues->GetPropertyULONG32(
"ClipFrameTop", ulTop)) &&
SUCCEEDED(pValues->GetPropertyULONG32(
"ClipFrameBottom", ulBottom)))
{
retVal = HXR_OUTOFMEMORY;
m_pClipRect = (HXxRect*) new HXxRect;
if (m_pClipRect)
{
m_pClipRect->left = (INT32) ulLeft;
m_pClipRect->right = (INT32) ulRight;
m_pClipRect->top = (INT32) ulTop;
m_pClipRect->bottom = (INT32) ulBottom;
retVal = HXR_OK;
}
}
}
HX_RELEASE(pValues);
}
HX_RELEASE(pSDPData);
#endif // HELIX_FEATURE_QUICKTIME
if (SUCCEEDED(retVal))
{
m_pVideoFormat = CreateFormatObject(m_pHeader);
retVal = HXR_OUTOFMEMORY;
if (m_pVideoFormat)
{
m_pVideoFormat->AddRef();
retVal = HXR_OK;
}
}
if (SUCCEEDED(retVal))
{
retVal = m_pVideoFormat->Init(pHeader);
}
if (SUCCEEDED(retVal))
{
m_ulEarlyFrameTol = GetEarlyFrameTolerance();
m_ulLateFrameTol = GetLateFrameTolerance();
m_ulMaxOptimizedVideoLead = GetMaxOptimizedVideoLead();
m_ulMaxSleepTime = GetMaxSleepTime();
m_ulNoFramesPollingInterval = GetNoFramesPollingInterval();
m_ulBltPacketQueueSize = GetBltPacketQueueSize();
m_ulSyncGoalSmoothingDepth = GetSyncGoalSmoothingDepth();
m_ulSpeedupGoalSmoothingDepth = GetSpeedupGoalSmoothingDepth();
m_ulMaxBadSeqSamples = GetMaxBadSeqSamples();
}
// Setup preroll
if (SUCCEEDED(retVal))
{
BOOL bSetNewPreroll = FALSE;
m_ulPreroll = 0;
ULONG32 ulMinPreroll = m_pVideoFormat->GetMinimumPreroll(pHeader);
ULONG32 ulMaxPreroll = m_pVideoFormat->GetMaximumPreroll(pHeader);
// Check that the stream header has a preroll value. If not...
pHeader->GetPropertyULONG32("Preroll", m_ulPreroll);
if (m_ulPreroll == 0)
{
// ... let's use default value.
m_ulPreroll = m_pVideoFormat->GetDefaultPreroll(pHeader);
bSetNewPreroll = TRUE;
}
else if( m_ulPreroll > ulMaxPreroll )
{
m_ulPreroll = ulMaxPreroll;
bSetNewPreroll = TRUE;
}
else if (m_ulPreroll < ulMinPreroll)
{
m_ulPreroll = ulMinPreroll;
bSetNewPreroll = TRUE;
}
if (bSetNewPreroll)
{
pHeader->SetPropertyULONG32("Preroll", m_ulPreroll);
}
}
// Determine Average Bitrate
if (SUCCEEDED(retVal))
{
if (FAILED(pHeader->GetPropertyULONG32("AvgBitRate", m_ulAvgBitRate)))
{
m_ulAvgBitRate = 0;
}
}
// Create Blt Queue
if (SUCCEEDED(retVal))
{
m_pBltPacketQueue = new CRingBuffer(m_ulBltPacketQueueSize);
retVal = HXR_OUTOFMEMORY;
if (m_pBltPacketQueue)
{
retVal = HXR_OK;
}
}
return retVal;
}
/////////////////////////////////////////////////////////////////////////////
// Method:
// CVideoRenderer::CheckStreamVersions
// copied from CRealAudioRenderer
HX_RESULT CVideoRenderer::CheckStreamVersions(IHXValues* pHeader)
{
// check stream and content versions so an upgrade can
// be called if necessary...
HX_RESULT pnr = HXR_OK;
BOOL bVersionOK = TRUE;
UINT32 ulStreamVersion = 0;
UINT32 ulContentVersion = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -