📄 winsurf2.cpp
字号:
m_TimeStamps.AddSample();
#endif
}
else
{
// If we are in fallback mode, make them manually redraw
if (m_bFallbackSurfaceCreated && HX_OVERLAY_BLT!=m_nBltMode && !m_bYUVBlending)
{
// If no src rect is specified, use surface
if (!prSrcRect->right && !prSrcRect->bottom)
{
prSrcRect->right = m_allocatedFallbackSize.cx;
prSrcRect->bottom = m_allocatedFallbackSize.cy;
}
SetLastScale(prSrcRect, prDestRect);
_ConstructRects( *prSrcRect,
*prDestRect,
FALSE,
nNumRects,
&paSrcRects,
&paDestRects);
memcpy(&m_lastSrcRect, paSrcRects, sizeof(*paSrcRects)); /* Flawfinder: ignore */
EnterCriticalSection(&m_csFallback);
for( int j=0 ; j<nNumRects ; j++ )
{
hr = WinDrawSurface_Blt(pWindraw, &m_fallbackSurface, (RECT*)&paDestRects[j], (RECT*)&paSrcRects[j]);
}
LeaveCriticalSection(&m_csFallback);
HX_VECTOR_DELETE(paSrcRects);
HX_VECTOR_DELETE(paDestRects);
#if !defined(_GOLD) && 0
m_TimeStamps.AddSample();
#endif
}
}
}
return hr;
}
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())
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -