📄 vidrend.cpp
字号:
}/////////////////////////////////////////////////////////////////////////// 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 32STDMETHODIMP 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_DECODESTDMETHODIMP_(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 */STDMETHODIMPCVideoRenderer::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;}STDMETHODIMPCVideoRenderer::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;};STDMETHODIMPCVideoRenderer::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;#endif // HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO default: // nothing to do break; } return retVal;}// *** IUnknown methods ***/***************************************************************************** IUnknown::AddRef ref: hxcom.h** This routine increases the object reference count in a thread safe* manner. The reference count is used to manage the lifetime of an object.* This method must be explicitly called by the user whenever a new* reference to an object is used.*/STDMETHODIMP_(ULONG32) CVideoRenderer::AddRef(){ return InterlockedIncrement(&m_lRefCount);}/***************************************************************************** IUnknown::Release ref: hxcom.h** This routine decreases the object reference count in a thread safe* manner, and deletes the object if no more references to it exist. It must* be called explicitly by the user whenever an object is no longer needed.*/STDMETHODIMP_(ULONG32) CVideoRenderer::Release(){ if (InterlockedDecrement(&m_lRefCount) > 0) { return m_lRefCount; } delete this; return 0;}/***************************************************************************** IUnknown::QueryInterface ref: hxcom.h** This routine indicates which interfaces this object supports. If a given* interface is supported, the object's reference count is incremented, and* a reference to that interface is returned. Otherwise a NULL object and* error code are returned. This method is called by other objects to* discover the functionality of this object.*/STDMETHODIMP CVideoRenderer::QueryInterface(REFIID riid, void** ppvObj){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -