📄 winsurf2.cpp
字号:
if (m_bFlushing) { return HXR_COULD_NOT_DISPLAY; } INT32 nIndex = -1; // Add this frame to the list and alert the render thread tFrameElement *pItem = new tFrameElement; memset(pItem, 0, sizeof(*pItem)); pItem->lTimeStamp = lTime; pItem->nBltMode = HX_OVERLAY_BLT; pItem->ulFlags = ulFlags; pItem->rcSrc = *prSrcRect; pItem->rcDst = *prDestRect; pItem->bAlpha = m_bFrameHasHWAlphaBlend; pItem->count = pVidStruct->ulCount; pItem->bmi = m_bmi; // If we are in system memory mode, we must blt to hardware ourselves if (m_bUseSysMemSurface) { m_bUseSysMemSurface = FALSE; BOOL bAlphaCheck = m_bDoAlphaCheck; // Grab a hw buffer and convert the sys mem image to hw yuv. UCHAR *pScratchVidMem = NULL; INT32 nPitch = 0; HXBitmapInfoHeader bmiTemp; memset( &bmiTemp, 0, sizeof( bmiTemp ) ); // We need a hw mem buffer, so disable the alpha blending check // that returns system mem. m_bDoAlphaCheck = FALSE; VideoMemStruct vs; memset(&vs, 0, sizeof(vs)); GetVideoMem(&vs, HX_WAIT_FOREVER); pScratchVidMem = vs.pVidMem; nPitch = vs.lPitch; bmiTemp = vs.bmi; if (pScratchVidMem) { HXxSize srcSize = {bmiTemp.biWidth, bmiTemp.biHeight}; SourceInputStruct input = {&m_pSysMemSurf[m_nNextSysMemBuffer].pBuffer, &m_nSysMemSurfPitch, 1}; ColorConvert(m_nSysMemSurfID, &m_allocatedSysMemSurfSize, prSrcRect, &input, bmiTemp.biCompression, pScratchVidMem, &srcSize, prDestRect, nPitch); ReleaseSurface(&vs, FALSE); } m_bDoAlphaCheck = bAlphaCheck; if (!pScratchVidMem) goto FAILURE; pItem->nIndex = m_nNextSysMemBuffer; if (++m_nNextSysMemBuffer == m_nSysMemSurfCount) m_nNextSysMemBuffer = 0; } // Alpha blend if necessary if (pVidStruct->pAlphaList && pVidStruct->ulCount) { HXxSize size = {pVidStruct->bmi.biWidth, pVidStruct->bmi.biHeight}; YuvAlphaBlend(pVidStruct->pAlphaList, pVidStruct->ulCount, pVidStruct->pVidMem, pVidStruct->bmi.biCompression, pVidStruct->lPitch, &size); } // If our last lock was not using overlay, use our offscreen blt if (m_bScratchSurface) { if (!m_fallbackSurface.dd.lpDDSurface) goto FAILURE; pItem->nBltMode = HX_BLT_YUV_STRETCH; pItem->pAlphaList = pVidStruct->pAlphaList; ResetEvent(m_hFallbackEmpty); } // Our last lock was using gdi else if (m_bGDISurface) { pItem->nBltMode = HX_BASIC_BLT; pItem->pAlphaList = pVidStruct->pAlphaList; pItem->nIndex = m_nNextGdiSurface; } else { // Advance the overlay surface list int nNewIndex = nIndex; if (!m_surface.dd.lpDDSurface) goto FAILURE; CWinBaseRootSurface *pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface(); if (!pSurface) goto FAILURE; WINDRAW *pWindraw = pSurface->GetWinDraw(); if (HXR_OK != WinDraw_AdvanceSurface (pWindraw, &m_surface, nNewIndex)) goto FAILURE; pItem->nIndex = nNewIndex; pItem->nBltMode = HX_OVERLAY_BLT; } // Increase the mutex lock count so another thread does not lock // it before we queue this frame or prevent us from drawing immediately. WaitForSingleObject(m_hSurfaceMutex, INFINITE); // We delete the alphalist in DisplayFrame in yuv_stretch mode. ReleaseSurface(pVidStruct, FALSE, (pItem->nBltMode!=HX_BLT_YUV_STRETCH)); // Immediate display...don't queue if (ulFlags & HX_MODE_IMMEDIATE) { HRESULT hr; tFrameElement lastItem; for (int i=0; i<5; i++) { pItem->dwDDFlags = DDFLIP_WAIT; lastItem = *pItem; hr = DisplayFrame(pItem); // Need to try again if (DDERR_WASSTILLDRAWING == hr) { *pItem = lastItem; WaitForSingleObject(m_hAbort, 10); } // Probably can not async flip, so turn it off else if (DDERR_INVALIDPARAMS == hr && m_bUseVBlankFlip) { *pItem = lastItem; m_bUseVBlankFlip = FALSE; } else { // Abort this overaly surface on a failure if (DD_OK != hr && pItem->nBltMode == HX_OVERLAY_BLT) { CWinBaseRootSurface *pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface(); if (!pSurface) goto FAILURE; WINDRAW *pWindraw = pSurface->GetWinDraw(); WinDraw_DisplaySurface(pWindraw, &m_surface, pItem->dwDDFlags, pItem->nIndex, TRUE); } break; } } ReleaseMutex(m_hSurfaceMutex); delete pItem;#if !defined(_GOLD) && 0 m_TimeStamps.AddSample();#endif return HXR_OK; } EnterCriticalSection(&m_csList); m_pListOfFrames->AddTail((void*)pItem); LeaveCriticalSection(&m_csList); ReleaseSemaphore(m_hFrameSem, 1, NULL); ReleaseMutex(m_hSurfaceMutex);#if !defined(_GOLD) && 0 m_TimeStamps.AddSample();#endif return HXR_OK; FAILURE: delete pItem; return HXR_FAIL;}STDMETHODIMP_(void) CWinSurface2::Flush(){ m_bFlushing = TRUE; //This needs to be before the wait on m_hSurfaceMutex because if //you hit stop before we start blt'ing frames you could be waiting //a long time before it wakes up. At least in the case for live //streams where we don't have the server/ff seek back to the //nearest keyframe and send data. Some streams have keyframes //every 10seconds or so. PulseEvent(m_hAbort); WaitForSingleObject(m_hSurfaceMutex, INFINITE); CWinBaseRootSurface *pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface(); WINDRAW *pWindraw = pSurface->GetWinDraw(); // Cancel and pending frames WinDraw_CacelPendingDisplay (pWindraw, &m_surface); PulseEvent(m_hForceRender); Sleep(5); // Wait until our queue count reaches 0 int nCount = m_pListOfFrames->GetCount(); while (nCount) { WinDraw_CacelPendingDisplay (pWindraw, &m_surface); PulseEvent(m_hAbort); PulseEvent(m_hForceRender); Sleep(5); nCount = m_pListOfFrames->GetCount(); } ResetBufferTimes(0); ReleaseMutex(m_hSurfaceMutex); m_bFlushing = FALSE;}void CWinSurface2::ResetBufferTimes(INT32 nTime){ // Reset all buffer times if (m_surface.dwBackBufferCount) { for (UINT32 i=0; i<m_surface.dwBackBufferCount+1; i++) m_surface.dd.lpChain[i].dTimeAvailable = nTime; }}STDMETHODIMP CWinSurface2::PresentIfReady(){ HX_RESULT hr = E_FAIL; if (!m_pTimeLine | m_bIngnorePresentIfReady) return hr; UINT32 ulTime = 0; if (HXR_TIMELINE_SUSPENDED != m_pTimeLine->GetTimeLineValue(ulTime)) { if (((m_nLastDisplayTime > 0) && (m_nLastDisplayTime - (INT32)ulTime < 0))) { #ifdef LOG_JITTER_DATA FILE *fp = fopen(JITTER_LOG_FILE, "a+"); if (fp) { fprintf(fp, "PresentIfReady Interrupt clock %ld last display %ld\n", ulTime, m_nLastDisplayTime); fclose(fp); } #endif PulseEvent(m_hForceRender); Sleep(0);#ifdef _DEBUG //OutputDebugString("PresentIfReady Interrupt\n");#endif hr = HXR_OK; } } return hr;}HX_RESULT CWinSurface2::DisplayFrame(tFrameElement* pItem){ HRESULT hr = HXR_OK, hrTimeLine = HXR_OK; HXxSize rcSize = {0,0}; int nNumRects = 0; BOOL bSub1x = FALSE; m_pSite->_TLSLock(); CWinBaseRootSurface *pSurface = (CWinBaseRootSurface*)m_pSite->GetRootSurface(); if (!pSurface) { m_pSite->_TLSUnlock(); return HXR_FAIL; } WINDRAW *pWindraw = pSurface->GetWinDraw(); // Ensure our site is visible before displaying BOOL bVisibleSite = (!HXEmptyRegion(m_pSite->m_Region)|| pItem->count || pItem->bAlpha) && m_pSite->IsSiteVisible() && !m_pSite->_FadeTransitionActive(); if (pItem->nBltMode == HX_OVERLAY_BLT) { // If no src rect is specified, use surface if (!pItem->rcSrc.right && !pItem->rcSrc.bottom) { pItem->rcSrc.right = m_surfaceSize.cx; pItem->rcSrc.bottom = m_surfaceSize.cy; } // Put the frame on the screen int nIndex = pItem->nIndex-1; if (nIndex < 0) nIndex = m_nBackBufferCount; if (pItem->dwDDFlags & DDFLIP_WAIT == DDFLIP_WAIT) { // Immediate mode blits have no calculated timaAvailable; use // the current time: pItem->dTimeAvailable = GetMSTickDouble32(); } m_surface.dd.lpChain[nIndex].dTimeAvailable = pItem->dTimeAvailable; m_surface.dd.lpChain[pItem->nIndex].dTimeAvailable = 0; hr = WinDraw_DisplaySurface(pWindraw, &m_surface, pItem->dwDDFlags, pItem->nIndex, m_bFlushing);#ifdef LOG_JITTER_DATA UINT32 ulTimeAfter = 0; m_pTimeLine->GetTimeLineValue(ulTimeAfter); FILE *fp = fopen(JITTER_LOG_FILE, "a+"); if (fp) { UINT32 dwScanLine = 0; WinDraw2_GetScanLine(pWindraw, &dwScanLine); fprintf(fp, "Calling flip: scan line %ld clock after %ld ts %ld jitter %ld\n\n", dwScanLine, ulTimeAfter, pItem->lTimeStamp, (INT32)(pItem->lTimeStamp-ulTimeAfter)); fclose(fp); }#endif //LOG_JITTER_DATA if (DD_OK == hr && bVisibleSite) { m_nLastBltMode = HX_OVERLAY_BLT; // Make sure we are painting colorkey in fullscreen mode. // We will fix this when fillcolor key is fixed. if (m_pSite->m_pTopLevelSite && m_pSite->m_pTopLevelSite->m_bInFullScreen) { if (++m_ulFillColoryKeyCount < 15) memset(&m_rcLast, 0, sizeof(m_rcLast)); } else m_ulFillColoryKeyCount = 0; if (!IsShrinking() || _AllowsOverlayShrinking()) { // Restore overlay if (HX_OVERLAY_BLT != m_nBltMode) { ForceGDIMode(FALSE); } // If no src rect is specified, use surface if (!pItem->rcDst.right && !pItem->rcDst.bottom) { m_pSite->GetSize(rcSize); pItem->rcDst.right = rcSize.cx; pItem->rcDst.bottom = rcSize.cy; } SetLastScale(&pItem->rcSrc, &pItem->rcDst); double dScaleX = m_scaleFactorX, dScaleY = m_scaleFactorY; // Setup new src and dest rects.... _ConstructRects( pItem->rcSrc, pItem->rcDst, FALSE, nNumRects, &m_paSrcRects, &m_paDestRects); if (nNumRects != 1) { HXxPoint screenOffset = m_pSite->GetScreenOffset(); if (!m_paSrcRects) m_paSrcRects = (HXxRect*)malloc(sizeof(HXxRect)); if (!m_paDestRects) m_paDestRects = (HXxRect*)malloc(sizeof(HXxRect));; m_paSrcRects[0] = pItem->rcSrc; m_paDestRects[0] = pItem->rcDst; m_paSrcRects[0].left += screenOffset.x; m_paSrcRects[0].top += screenOffset.y; m_paSrcRects[0].right += screenOffset.x; m_paSrcRects[0].bottom += screenOffset.y; } if (m_paSrcRects && m_paDestRects) { ForceUpdateOverlay(&m_paDestRects[0], &m_paSrcRects[0], HX_OVER_SHOW|HX_OVER_KEYDEST, TRUE); } if (m_bNeedColorKeyFilled) { m_bDisableFillColorKey = FALSE; _FillColorKey(); } // Alpha blended images are drawn before the video so the scaling gets messed up on // static images. Force a redraw to correct the problem. if ((dScaleX != m_scaleFactorX || dScaleY != m_scaleFactorY) && m_pSite->IsFullScreen())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -