📄 halvpe.cpp
字号:
void SMI::VPE_SetCap(DWORD dwMask, DWORD dwVal)
{
DWORD dwMode = PEEK_32(CAPTURE_CONTROL);
dwMode = (dwMode & dwMask) | dwVal;
POKE_32(CAPTURE_CONTROL, dwMode);
}
BOOL SMI::VPE_WaitForVSync(DWORD dwTimeOut)
{
#ifndef DISABLE_INTERRUPT_MANAGEMENT
DWORD retVal = FALSE;
if (!m_bZVPortEvent) {
// Worst case : we are prempted right after m_bZVPortEvent is set to
// TRUE, and then we hit a vertical retrace. This causes m_bZVPortEvent to
// be harmlessly set with no threads waiting. We also miss that vsync.
m_bZVPortEvent = TRUE;
DWORD retWait = WaitForSingleObject(m_hZVPortEvent,
dwTimeOut);
m_bZVPortEvent = FALSE;
switch (retWait) {
case WAIT_OBJECT_0:
retVal = TRUE;
break;
case WAIT_TIMEOUT:
DEBUGMSG(GPE_ZONE_WARNING, (L"Timeout waiting for vertical retrace!\n"));
break;
case WAIT_FAILED:
DEBUGMSG(GPE_ZONE_ERROR,(L"Wait on vertical retrace failed\n"));
break;
}
}
else {
DEBUGMSG(GPE_ZONE_ERROR, (L"Another thread is already waiting on the vsync!\n"));
}
return retVal;
#else
return FALSE;
#endif
}
void vpeIntHandlerEntry(SMI* pSMI)
{
pSMI->VPE_IntHandler();
}
void SMI::VPE_IntHandler()
{
#ifndef DISABLE_INTERRUPT_MANAGEMENT
if (m_bZVPortEvent)
{
SetEvent(m_hZVPortEvent);
}
POKE_32(RAW_INT_STATUS, FIELD_SET(0, RAW_INT_STATUS, ZVPORT, CLEAR));
VPE_ProcessCapture();
#endif
}
int SMI::VPE_CurrentBuffer()
{
DWORD capture_ctrl = 0;
capture_ctrl = PEEK_32(CAPTURE_CONTROL);
return(FIELD_GET(capture_ctrl, CAPTURE_CONTROL, FIELD));
}
void SMI::VPE_ProcessCapture()
{
#ifndef DISABLE_INTERRUPT_MANAGEMENT
PLIST_ENTRY pEntry;
PFLIP_EXTENSION pFlipExt;
return;
if(!m_Autoflip.pCaptureEntry1 && !m_Autoflip.pCaptureEntry2)
{
// Just start.
pEntry = RemoveHeadList(&m_Autoflip.EmptyFrameQueue);
pFlipExt = (PFLIP_EXTENSION)(((PUCHAR)pEntry) - FIELDOFFSET(FLIP_EXTENSION, ListEntry));
VPE_SetDst(pFlipExt->fpVidMem);
m_Autoflip.pCaptureEntry1 = pEntry;
pEntry = RemoveHeadList(&m_Autoflip.EmptyFrameQueue);
pFlipExt = (PFLIP_EXTENSION)(((PUCHAR)pEntry) - FIELDOFFSET(FLIP_EXTENSION, ListEntry));
VPE_SetDst2(pFlipExt->fpVidMem);
m_Autoflip.pCaptureEntry2 = pEntry;
}
else if(VPE_CurrentBuffer() == 1)
{
// Buffer2 is just filled.
// 1) Complete the display field if exists.
if(m_Autoflip.pDisplayEntry)
{
InsertTailList(&m_Autoflip.EmptyFrameQueue, m_Autoflip.pDisplayEntry);
}
// 2) Display the newly captured field.
pEntry = m_Autoflip.pCaptureEntry2;
pFlipExt = (PFLIP_EXTENSION)(((PUCHAR)pEntry) - FIELDOFFSET(FLIP_EXTENSION, ListEntry));
VPE_EnableOverlayWindow(pFlipExt->fpVidMem);
// Correct BOB display.
if(VPE_IsEvenField())
{
// The captured field is even field.
POKE_32(VIDEO_INITIAL_SCALE,
FIELD_VALUE(0, VIDEO_INITIAL_SCALE, FB_1, 0) |
FIELD_VALUE(0, VIDEO_INITIAL_SCALE, FB_0, 0) |
0);
}
else
{
// The captured field is odd field.
POKE_32(VIDEO_INITIAL_SCALE,
FIELD_VALUE(0, VIDEO_INITIAL_SCALE, FB_1, 0x800) |
FIELD_VALUE(0, VIDEO_INITIAL_SCALE, FB_0, 0x800) |
0);
}
m_Autoflip.pDisplayEntry = pEntry;
// 3) Set the next capture field.
pEntry = RemoveHeadList(&m_Autoflip.EmptyFrameQueue);
pFlipExt = (PFLIP_EXTENSION)(((PUCHAR)pEntry) - FIELDOFFSET(FLIP_EXTENSION, ListEntry));
VPE_SetDst2(pFlipExt->fpVidMem);
m_Autoflip.pCaptureEntry2 = pEntry;
}
else
{
// Buffer1 is just filled.
// 1) Complete the display field if exists.
if(m_Autoflip.pDisplayEntry)
{
InsertTailList(&m_Autoflip.EmptyFrameQueue, m_Autoflip.pDisplayEntry);
}
// 2) Display the newly captured field.
pEntry = m_Autoflip.pCaptureEntry1;
pFlipExt = (PFLIP_EXTENSION)(((PUCHAR)pEntry) - FIELDOFFSET(FLIP_EXTENSION, ListEntry));
VPE_EnableOverlayWindow(pFlipExt->fpVidMem);
// Correct BOB display.
if(VPE_IsEvenField())
{
// The captured field is even field.
POKE_32(VIDEO_INITIAL_SCALE,
FIELD_VALUE(0, VIDEO_INITIAL_SCALE, FB_1, 0) |
FIELD_VALUE(0, VIDEO_INITIAL_SCALE, FB_0, 0) |
0);
}
else
{
// The captured field is odd field.
POKE_32(VIDEO_INITIAL_SCALE,
FIELD_VALUE(0, VIDEO_INITIAL_SCALE, FB_1, 0x800) |
FIELD_VALUE(0, VIDEO_INITIAL_SCALE, FB_0, 0x800) |
0);
}
m_Autoflip.pDisplayEntry = pEntry;
// 3) Set the next capture field.
pEntry = RemoveHeadList(&m_Autoflip.EmptyFrameQueue);
pFlipExt = (PFLIP_EXTENSION)(((PUCHAR)pEntry) - FIELDOFFSET(FLIP_EXTENSION, ListEntry));
VPE_SetDst(pFlipExt->fpVidMem);
m_Autoflip.pCaptureEntry1 = pEntry;
}
#endif
}
// When use software autoflip, we need minimum 3 field buffers and maximum 8 field buffers.
// Inside m_Autoflip structure,
// EmptyFrameQueue queues all the empty buffers, initially it contains all the field surfaces allocated by user app;
// pCaptureEntry1 desinates the first capture buffer when using hardware double buffer capture, initially it's NULL;
// pCaptureEntry2 desinates the second capture buffer when using hardware double buffer capture, initially it's NULL;
// pDisplayEntry desinates the buffer which is being displayed, initially it's NULL.
void SMI::VPE_InitSwAutoflip(DWORD *pInput)
{
#ifndef DISABLE_INTERRUPT_MANAGEMENT
DWORD numOfSurfaces = pInput[0];
InitializeListHead(&m_Autoflip.EmptyFrameQueue);
m_Autoflip.pCaptureEntry1 = NULL;
m_Autoflip.pCaptureEntry2 = NULL;
m_Autoflip.pDisplayEntry = NULL;
for(DWORD i=0; i<numOfSurfaces; i++)
{
m_Autoflip.FlipEntries[i].surfaceIndex = i;
m_Autoflip.FlipEntries[i].fpVidMem = pInput[i+1];
InsertTailList(&m_Autoflip.EmptyFrameQueue, &m_Autoflip.FlipEntries[i].ListEntry);
}
#endif
}
void SMI::VPE_InitInterrupt()
{
#ifndef DISABLE_INTERRUPT_MANAGEMENT
m_bZVPortEvent = FALSE;
m_hZVPortEvent = CreateEvent(NULL,
FALSE, // Auto-reset
FALSE, // Initially not signaled
NULL);
if (m_hZVPortEvent == NULL)
{
DEBUGMSG(GPE_ZONE_ERROR, (TEXT("SMI::InitZVPortInterrupt Failed!\r\n")));
m_bZVPortEvent = TRUE;
}
// Register PWM interrupt handler
RegisterHandler(
vpeIntHandlerEntry,
FIELD_SET(0, INT_MASK, ZVPORT, ENABLE));
#endif //DISABLE_INTERRUPT_MANAGEMENT
}
void SMI::VPE_DisableInterrupt()
{
#ifndef DISABLE_INTERRUPT_MANAGEMENT
// Register PWM interrupt handler
DisableHandler(
FIELD_SET(0, INT_MASK, ZVPORT, ENABLE));
if (m_hZVPortEvent != NULL)
{
if (m_bZVPortEvent)
{
SetEvent(m_hZVPortEvent);
Sleep(200);
}
m_bZVPortEvent = TRUE;
CloseHandle(m_hZVPortEvent);
}
#endif //DISABLE_INTERRUPT_MANAGEMENT
}
ULONG SMI::HandleSMIVPEAPI(ULONG cjIn, PVOID pvIn, ULONG cjOut, PVOID pvOut)
{
int RetVal = 0; // Not Supported
if (((cjIn >= sizeof(SMIVPEAPI)) && (pvIn != NULL)) &&
((cjOut >= sizeof(SMIVPEAPI)) && (pvOut != NULL)))
{
SMIVPEAPI *pSmiVpeOut = (SMIVPEAPI *)pvOut;
SMIVPEAPI *pSmiVpe = (SMIVPEAPI *)pvIn;
DWORD dwMask = 0;
RetVal = -1;
switch (pSmiVpe->dwCommand)
{
case SMIVPEAPI_FIELD_SWAP:
RetVal = 1;
if (pSmiVpe->dwParam == SMIVPEAPI_ENABLE)
VPE_EnableFieldSwap();
else if (pSmiVpe->dwParam == SMIVPEAPI_DISABLE)
VPE_DisableFieldSwap();
else
RetVal = -2;
break;
case SMIVPEAPI_BYTE_SWAP:
RetVal = 1;
if (pSmiVpe->dwParam == SMIVPEAPI_ENABLE)
VPE_EnableByteSwap();
else if (pSmiVpe->dwParam == SMIVPEAPI_DISABLE)
VPE_DisableByteSwap();
else
RetVal = -2;
break;
case SMIVPEAPI_UV_SWAP:
RetVal = 1;
dwMask = FIELD_SET(0, CAPTURE_CONTROL, UV_SWAP, ENABLE);
if (pSmiVpe->dwParam == SMIVPEAPI_ENABLE)
VPE_SetCap(dwMask, dwMask);
else if (pSmiVpe->dwParam == SMIVPEAPI_DISABLE)
VPE_SetCap(dwMask, 0);
else
RetVal = -2;
break;
case SMIVPEAPI_CAPTURE_SIZE:
RetVal = 1;
dwMask = FIELD_SET(0, CAPTURE_CONTROL, CAPTURE_SIZE, 8);
if (pSmiVpe->dwParam == SMIVPEAPI_8BIT)
VPE_SetCap(dwMask, dwMask);
else if (pSmiVpe->dwParam == SMIVPEAPI_16BIT)
VPE_SetCap(dwMask, 0);
else
RetVal = -2;
break;
case SMIVPEAPI_FORMAT:
RetVal = 1;
dwMask = FIELD_SET(0, CAPTURE_CONTROL, CAPTURE_FORMAT, RGB);
if (pSmiVpe->dwParam == SMIVPEAPI_RGB)
VPE_SetCap(dwMask, dwMask);
else if (pSmiVpe->dwParam == SMIVPEAPI_YUV)
VPE_SetCap(dwMask, 0);
else
RetVal = -2;
break;
case SMIVPEAPI_CLOCK_POLARITY:
RetVal = 1;
dwMask = FIELD_SET(0, CAPTURE_CONTROL, CLOCK_POLARITY, ACTIVE_LOW);
if (pSmiVpe->dwParam == SMIVPEAPI_ACTIVE_LOW)
VPE_SetCap(dwMask, dwMask);
else if (pSmiVpe->dwParam == SMIVPEAPI_ACTIVE_HIGH)
VPE_SetCap(dwMask, 0);
else
RetVal = -2;
break;
case SMIVPEAPI_HREF_PHASE:
RetVal = 1;
dwMask = FIELD_SET(0, CAPTURE_CONTROL, HREF_PHASE, ACTIVE_LOW);
if (pSmiVpe->dwParam == SMIVPEAPI_ACTIVE_LOW)
VPE_SetCap(dwMask, dwMask);
else if (pSmiVpe->dwParam == SMIVPEAPI_ACTIVE_HIGH)
VPE_SetCap(dwMask, 0);
else
RetVal = -2;
break;
case SMIVPEAPI_VSYNC_PHASE:
RetVal = 1;
dwMask = FIELD_SET(0, CAPTURE_CONTROL, VSYNC_PHASE, ACTIVE_LOW);
if (pSmiVpe->dwParam == SMIVPEAPI_ACTIVE_LOW)
VPE_SetCap(dwMask, dwMask);
else if (pSmiVpe->dwParam == SMIVPEAPI_ACTIVE_HIGH)
VPE_SetCap(dwMask, 0);
else
RetVal = -2;
break;
case SMIVPEAPI_FIELD_DETECT:
RetVal = 1;
dwMask = FIELD_SET(0, CAPTURE_CONTROL, FIELD_DETECT, FALLING);
if (pSmiVpe->dwParam == SMIVPEAPI_FALLING)
VPE_SetCap(dwMask, dwMask);
else if (pSmiVpe->dwParam == SMIVPEAPI_RISING)
VPE_SetCap(dwMask, 0);
else
RetVal = -2;
break;
case SMIVPEAPI_2TO1HSHRINK:
RetVal = 1;
dwMask = FIELD_SET(0, CAPTURE_CONTROL, 2TO1_HORIZONTAL_SHRINK, ENABLE);
if (pSmiVpe->dwParam == SMIVPEAPI_ENABLE)
VPE_SetCap(dwMask, dwMask);
else if (pSmiVpe->dwParam == SMIVPEAPI_DISABLE)
VPE_SetCap(dwMask, 0);
else
RetVal = -2;
break;
case SMIVPEAPI_2TO1VSHRINK:
RetVal = 1;
dwMask = FIELD_SET(0, CAPTURE_CONTROL, 2TO1_VERTICAL_SHRINK, ENABLE);
if (pSmiVpe->dwParam == SMIVPEAPI_ENABLE)
VPE_SetCap(dwMask, dwMask);
else if (pSmiVpe->dwParam == SMIVPEAPI_DISABLE)
VPE_SetCap(dwMask, 0);
else
RetVal = -2;
break;
case SMIVPEAPI_HAVE:
RetVal = 1;
dwMask = FIELD_SET(0, CAPTURE_CONTROL, HORIZONTAL_AVE, ENABLE);
if (pSmiVpe->dwParam == SMIVPEAPI_ENABLE)
VPE_SetCap(dwMask, dwMask);
else if (pSmiVpe->dwParam == SMIVPEAPI_DISABLE)
VPE_SetCap(dwMask, 0);
else
RetVal = -2;
break;
case SMIVPEAPI_VIDEO_VINTERPOLATE:
RetVal = 1;
if (pSmiVpe->dwParam == SMIVPEAPI_ENABLE)
Video_SetVerticalMode(INTERPOLATE);
else if (pSmiVpe->dwParam == SMIVPEAPI_DISABLE)
Video_SetVerticalMode(REPLICATE);
else
RetVal = -2;
break;
case SMIVPEAPI_VIDEO_HINTERPOLATE:
RetVal = 1;
if (pSmiVpe->dwParam == SMIVPEAPI_ENABLE)
Video_SetHorizontalMode(INTERPOLATE);
else if (pSmiVpe->dwParam == SMIVPEAPI_DISABLE)
Video_SetHorizontalMode(REPLICATE);
else
RetVal = -2;
break;
}
}
else
{
RetVal = -1;
}
if (RetVal == -1)
SetLastError (ERROR_INVALID_PARAMETER);
return (ULONG) RetVal;
}
#endif // VPE_ENABLE
#endif // DD_ENABLE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -