📄 cameracode.cpp
字号:
//----------------------------------------------------------------------
// GetNextStreamFrame - Returns the next available video frame.
//
int GetNextStreamFrame (DWORD dwContext, PBYTE *ppFrame, DWORD *pdwFrameSize,
DWORD dwFlags, DWORD dwTimeout)
{
PCAMSTATE pcs = (PCAMSTATE)dwContext;
GETFRAMESTRUCT gfsIn;
GETFRAMESTRUCTOUT gfsOut;
DWORD dwBytes;
BOOL f;
int rc = 0;
gfsIn.cbSize = sizeof (GETFRAMESTRUCT);
gfsIn.dwFlags = dwFlags;
if (dwFlags & GETFRAMEFLAG_FREEBUFF_VALID)
gfsIn.pFrameDataRet = *ppFrame;
gfsIn.dwTimeout = dwTimeout;
memset (&gfsOut, 0, sizeof (GETFRAMESTRUCTOUT));
gfsOut.cbSize = sizeof (GETFRAMESTRUCTOUT);
// Call the driver
f = DeviceIoControl (pcs->hCam, IOCTL_CAMERA_DEVICE_GETNEXTVIDEOFRAME,
&gfsIn, sizeof (GETFRAMESTRUCT),
&gfsOut, sizeof(GETFRAMESTRUCTOUT), &dwBytes, NULL);
if (f)
{
*ppFrame = gfsOut.pFrameData;
*pdwFrameSize = gfsOut.dwFrameSize;
}
if (!f) rc = GetLastError();
return rc;
}
//----------------------------------------------------------------------
// StreamFrameClose - Stops streaming of individual frames
//
int StreamFrameClose (DWORD dwContext)
{
PCAMSTATE pcs = (PCAMSTATE)dwContext;
DWORD dwBytes;
int rc = 0;
//
// Stop the stream
//
BOOL f = DeviceIoControl (pcs->hCam, IOCTL_CAMERA_DEVICE_STOPVIDEOSTREAM,
0, 0, 0, 0, &dwBytes, NULL);
if (!f) rc = GetLastError();
return rc;
}
//----------------------------------------------------------------------
// StartStreaming - Starts streaming video to a device context at
// the specified rectangle.
//
// If the .right and .bot fields of the rect structure are zero, the
// image will be sized based on its original format. If the rect
// structure is fully filled, the image will be sized to fit the rectangle
//
int StartStreaming (DWORD dwContext, HDC hdc, RECT *prect, WORD wFormat, WORD wFrame, DWORD dwInterval)
{
PCAMSTATE pcs = (PCAMSTATE)dwContext;
PTHREADSTRUCT pThd = (PTHREADSTRUCT)LocalAlloc (LPTR, sizeof (THREADSTRUCT));
if (!pThd) return ERROR_NOT_ENOUGH_MEMORY;
// Load parameter passing struct
pThd->wFormat = wFormat;
pThd->wFrame = wFrame;
pThd->rect = *prect;
pThd->dwInterval = dwInterval;
pThd->hdc = hdc;
pThd->pcs = pcs;
if (pcs->hCam != INVALID_HANDLE_VALUE)
{
pcs->fCont = TRUE;
pcs->hThread = CreateThread (NULL, 0, ReadFrameThread, (PVOID)pThd, 0, NULL);
if (pcs->hThread)
{
Sleep (0); //Let the thread start...
return 0;
}
else
return GetLastError();
}
return 0;
}
//----------------------------------------------------------------------
// Stops the video streaming
//
int StopStreaming (DWORD dwContext)
{
PCAMSTATE pcs = (PCAMSTATE)dwContext;
pcs->fCont = FALSE;
if (WaitForSingleObject (pcs->hThread, 5000) == WAIT_TIMEOUT)
{
DEBUGMSG (ZONE_ERROR, (TEXT("Can't shutdown ReadFrameThread\r\n")));
}
CloseHandle (pcs->hThread);
pcs->hThread = 0;
return 0;
}
//======================================================================
// ReadFrameThread - Reads each frame of MJPEG video from the driver,
// and displays it in a device context. This thread is started
// by the StartStreaming function.
//
DWORD WINAPI ReadFrameThread (PVOID pArg)
{
int rc = 0;
BOOL f;
DWORD dwBytes;
THREADSTRUCT Thd;
FORMATPROPS fmtData;
int nFrameCnt = 0;
DWORD dwTick = 0;
DWORD dwErr = 0;
DEBUGMSG (1, (TEXT ("ReadFrameThread++\r\n")));
if (!pArg)
return -1;
// Copy over params
Thd = *(PTHREADSTRUCT)pArg;
PCAMSTATE pcs = (PCAMSTATE)Thd.pcs;
LocalFree (pArg);
// Get information about the format
rc = GetFormatInformation (pcs, Thd.wFormat, Thd.wFrame, &fmtData);
if (rc)
{
return rc;
}
DEBUGMSG (ZONE_DECODING, (TEXT("Format %d\r\n"), fmtData.wFormatType));
DEBUGMSG (ZONE_DECODING, (TEXT("dwWidth %d\r\n"), fmtData.dwWidth));
DEBUGMSG (ZONE_DECODING, (TEXT("dwHeight %d\r\n"), fmtData.dwHeight));
DEBUGMSG (ZONE_DECODING, (TEXT("dwMaxBuff %d\r\n"), fmtData.dwMaxBuff));
DEBUGMSG (ZONE_DECODING, (TEXT("nNumInterval %d\r\n"), fmtData.nNumInterval));
// Initialize the conversion library
rc = InitDisplayFrame (NULL);
RECT rect;
// See if the caller wants to just specify position and not size
if ((Thd.rect.right == 0) && (Thd.rect.bottom == 0))
{
SetRect (&rect, Thd.rect.left, Thd.rect.top + 30,
Thd.rect.left + fmtData.dwWidth, Thd.rect.top + 30 + fmtData.dwHeight);
}
else
rect = Thd.rect;
// Parameters needed to start a stream
STARTVIDSTRUCT svStruct;
dwBytes = 0;
svStruct.cbSize = sizeof (STARTVIDSTRUCT);
svStruct.wFormatIndex = Thd.wFormat;
svStruct.wFrameIndex = Thd.wFrame;
svStruct.dwInterval = Thd.dwInterval;
svStruct.dwNumBuffs = NUMBUFFS;
svStruct.dwPreBuffSize = PREBUFFSIZE;
svStruct.dwPostBuffSize = 0;
//
// Start the video stream
//
f = DeviceIoControl (pcs->hCam, IOCTL_CAMERA_DEVICE_STARTVIDEOSTREAM,
(LPVOID)&svStruct, sizeof (STARTVIDSTRUCT),
0, 0, &dwBytes, NULL);
if (f)
{
// Call the driver for a frame
GETFRAMESTRUCT gfsIn;
GETFRAMESTRUCTOUT gfsOut;
memset (&gfsIn, 0, sizeof (GETFRAMESTRUCT));
gfsIn.cbSize = sizeof (GETFRAMESTRUCT);
gfsIn.dwFlags = GETFRAMEFLAG_GET_LATESTFRAME;
gfsIn.dwFlags |= GETFRAMEFLAG_TIMEOUT_VALID;
gfsIn.dwTimeout = 10000;
memset (&gfsOut, 0, sizeof (GETFRAMESTRUCTOUT));
gfsOut.cbSize = sizeof (GETFRAMESTRUCTOUT);
// Get the next frame of video
f = DeviceIoControl (pcs->hCam, IOCTL_CAMERA_DEVICE_GETNEXTVIDEOFRAME,
&gfsIn, sizeof (GETFRAMESTRUCT),
&gfsOut, sizeof(GETFRAMESTRUCTOUT), &dwBytes, NULL);
pcs->fCont = f;
// Used by motion detect code
IBitmapImage *pBitmapImageNew;
IBitmapImage *pBitmapImageOld = NULL;
BOOL fMotion;
while (pcs->fCont)
{
nFrameCnt++;
if (pcs->fDetectMotion)
{
HRESULT hr;
BMPFMT bmpf;
hr = GetBitMapImage (gfsOut.pFrameData, PREBUFFSIZE, gfsOut.dwFrameSize,
&pBitmapImageNew, (PBMPFMT)&bmpf);
if (SUCCEEDED (hr))
{
hr = DisplayBitmap (pBitmapImageNew, Thd.hdc, &rect);
if (SUCCEEDED (hr))
{
if (pBitmapImageOld)
{
fMotion = IsMotionDetected (pBitmapImageNew, pBitmapImageOld, &bmpf, 10);
}
//
pBitmapImageOld = pBitmapImageNew;
}
}
if (FAILED (hr))
{
dwErr++;
DEBUGMSG (ZONE_TIMING, (TEXT ("DisplayFrame-- %d mS to draw\r\n"), GetTickCount() - dwTick));
}
}
else
{
// Old method
if (pcs->fDraw)
{
// Draw frame in HDC
rc = DisplayFrame (gfsOut.pFrameData, PREBUFFSIZE, gfsOut.dwFrameSize, Thd.hdc, &rect);
if (rc) dwErr++;
DEBUGMSG (ZONE_TIMING, (TEXT ("DisplayFrame-- %d mS to draw\r\n"), GetTickCount() - dwTick));
}
fMotion = FALSE;
}
#ifdef DEBUG
{
TCHAR sz[128];
DWORD dwElapsed = GetTickCount() - dwTick;
if (dwElapsed == 0) dwElapsed++;
wsprintf (sz, TEXT("%3d x %3d Frame rate %4d fps Missed Frames %2d Errors %3d%% %s "),
fmtData.dwWidth, fmtData.dwHeight, 1000/dwElapsed, gfsOut.dwMissedFrames-1,
(dwErr*100)/nFrameCnt,
fMotion ? TEXT("Motion Detected!") : TEXT(" "));
ExtTextOut (Thd.hdc, Thd.rect.left+5, Thd.rect.top + 2, ETO_OPAQUE, NULL, sz, lstrlen (sz), 0);
}
#else //DEBUG
{
if (fMotion)
{
ExtTextOut (Thd.hdc, Thd.rect.left+5, Thd.rect.top + 2, ETO_OPAQUE, NULL,
TEXT("Motion Detected!"), lstrlen (TEXT("Motion Detected!")), 0);
}
}
#endif
dwTick = GetTickCount();
gfsIn.dwFlags = GETFRAMEFLAG_GET_LATESTFRAME | GETFRAMEFLAG_FREEBUFF_VALID;
gfsIn.pFrameDataRet = gfsOut.pFrameData;
gfsIn.dwFlags |= GETFRAMEFLAG_TIMEOUT_VALID;
gfsIn.dwTimeout = 10000;
// Call the driver
f = DeviceIoControl (pcs->hCam, IOCTL_CAMERA_DEVICE_GETNEXTVIDEOFRAME,
&gfsIn, sizeof (GETFRAMESTRUCT),
&gfsOut, sizeof(GETFRAMESTRUCTOUT), &dwBytes, NULL);
if (!f)
{
pcs->fCont = FALSE;
}
}
//
// Stop the stream
//
f = DeviceIoControl (pcs->hCam, IOCTL_CAMERA_DEVICE_STOPVIDEOSTREAM,
0, 0, 0, 0, &dwBytes, NULL);
}
else
{
DEBUGMSG (ZONE_ERROR, (TEXT("failure calling IOCTL_CAMERA_DEVICE_STARTVIDEOSTREAM rc %d\r\n"), GetLastError()));
pcs->fCont = FALSE;
}
// Clean up translation code
ReleaseDisplayFrame ();
DEBUGMSG (1, (TEXT ("ReadFrameThread--\r\n")));
return 0;
}
//----------------------------------------------------------------------
// GetStillImage - Returns a still from the driver
//
int GetStillImage (DWORD dwContext, WORD wFormat, WORD wFrame, PFORMATPROPS pFmt, PBYTE *ppData, DWORD *pdwSize)
{
int rc = 0;
VIDFORMATSTRUCT vf;
DWORD dwBytes, dwBuff;
BOOL f;
PCAMSTATE pcs = (PCAMSTATE)dwContext;
memset (&vf, 0, sizeof (vf));
vf.cbSize = sizeof (VIDFORMATSTRUCT);
vf.wFormatIndex = wFormat;
vf.wFrameIndex = wFrame;
*pdwSize = 0;
// See if we should allocate the buffer
if (*ppData == 0)
{
// Call to get the size of the buffer
f = DeviceIoControl (pcs->hCam, IOCTL_CAMERA_DEVICE_GETSTILLIMAGE,
&vf, sizeof (VIDFORMATSTRUCT), 0, 0, &dwBytes, NULL);
if (!f)
{
rc = GetLastError();
DEBUGMSG (ZONE_ERROR, (TEXT("failure calling IOCTL_CAMERA_DEVICE_GETSTILLIMAGE rc %d\r\n"), rc));
return rc;
}
// Allocate the buffer
*ppData = (PBYTE) LocalAlloc (LPTR, dwBytes);
if (*ppData == 0)
return ERROR_NOT_ENOUGH_MEMORY;
dwBuff = dwBytes;
}
// Call to get the image
f = DeviceIoControl (pcs->hCam, IOCTL_CAMERA_DEVICE_GETSTILLIMAGE,
&vf, sizeof (VIDFORMATSTRUCT), *ppData, dwBuff, &dwBytes, NULL);
if (!f)
{
rc = GetLastError();
DEBUGMSG (ZONE_ERROR, (TEXT("failure calling IOCTL_CAMERA_DEVICE_GETSTILLIMAGE rc %d\r\n"), rc));
} else
*pdwSize = dwBytes;
return rc;
}
//-------------------------------------------------------------------------
// Writes a MJPEG frame as a JPEG file
//
int WriteJPEG (LPTSTR lpszName, PBYTE pData, int nSize)
{
BYTE MJPGDHTSeg[0x1A4] = {
/* JPEG DHT Segment for YCrCb omitted from MJPG data */
0xFF,0xC4,0x01,0xA2,
0x00,0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x01,0x00,0x03,0x01,0x01,0x01,0x01,
0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0A,0x0B,0x10,0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,
0x00,0x01,0x7D,0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,
0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,0x24,
0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,0x29,0x2A,0x34,
0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56,
0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,
0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,
0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,
0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,
0xDA,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
0xF8,0xF9,0xFA,0x11,0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,
0x02,0x77,0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0,0x15,0x62,
0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26,0x27,0x28,0x29,0x2A,
0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56,
0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,
0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,
0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,
0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,
0xD9,0xDA,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
0xF9,0xFA
};
int rc = 0;
DWORD dwBytes;
HANDLE hFile = CreateFile (lpszName, GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
BYTE bHdr[] =
{
0xff,0xd8, // SOI
0xff,0xe0, // APP0
0x00,0x10, // APP0 Hdr size
0x4a,0x46,0x49,0x46,0x00, // ID string
0x01,0x01, // Version
0x00, // Bits per type
0x00, 0x00, // X density
0x00, 0x00, // Y density
0x00, // X Thumbnail size
0x00, // Y Thumbnail size
};
WriteFile (hFile, bHdr, sizeof (bHdr), &dwBytes, NULL);
// Write DHT color segment needed for stand-alone file
WriteFile (hFile, MJPGDHTSeg, sizeof (MJPGDHTSeg), &dwBytes, NULL);
// try removing AVI header from image
#if 1
int n = *(pData+4);
n = n << 8;
n += *(pData+5)+4;
PBYTE p2 = pData + n;
WriteFile (hFile, p2, nSize-n, &dwBytes, NULL);
#else
WriteFile (hFile, pData, nSize, &dwBytes, NULL);
#endif
DEBUGMSG (1, (TEXT("Write %d bytes to image file.\r\n"), dwBytes));
CloseHandle (hFile);
} else
rc = GetLastError();
return rc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -