📄 cameracode.cpp
字号:
if (hCam != INVALID_HANDLE_VALUE)
{
fCont = TRUE;
hThread = CreateThread (NULL, 0, ReadFrameThread, (PVOID)pThd, 0, NULL);
if (hThread)
{
Sleep (0); //Let the thread start...
return 0;
}
else
return GetLastError();
}
return 0;
}
//----------------------------------------------------------------------
// Stops the video streaming
//
int CCameraCode::StopStreaming ()
{
fCont = FALSE;
if (WaitForSingleObject (hThread, 5000) == WAIT_TIMEOUT)
{
;//DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Can't shutdown ReadFrameThread\r\n")));
}
CloseHandle (hThread);
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 CCameraCode::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;
CCameraCode *pCameracode=(CCameraCode*)Thd.pCamercode;
LocalFree (pArg);
// Get information about the format
rc = pCameracode->GetFormatInformation (Thd.wFormat, Thd.wFrame, &fmtData);
if (rc)
{
//printf ("Failure to get format data rc = %d\r\n", rc);
return rc;
}
// Initialize the conversion library
rc =pCameracode->pMjpe2bmp-> 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,
Thd.rect.left + fmtData.dwWidth, Thd.rect.top + 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 ( pCameracode->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 ( pCameracode->hCam, IOCTL_CAMERA_DEVICE_GETNEXTVIDEOFRAME,
&gfsIn, sizeof (GETFRAMESTRUCT),
&gfsOut, sizeof(GETFRAMESTRUCTOUT), &dwBytes, NULL);
pCameracode->fCont = f;
while ( pCameracode->fCont)
{
nFrameCnt++;
if (pCameracode->fDraw)
{
rc = pCameracode->pMjpe2bmp-> DisplayFrame (gfsOut.pFrameData, PREBUFFSIZE, gfsOut.dwFrameSize, Thd.hdc, &rect);
if (rc) dwErr++;
}
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 ( pCameracode->hCam, IOCTL_CAMERA_DEVICE_GETNEXTVIDEOFRAME,
&gfsIn, sizeof (GETFRAMESTRUCT),
&gfsOut, sizeof(GETFRAMESTRUCTOUT), &dwBytes, NULL);
if (!f)
{
//printf ("deviceioctl IOCTL_CAMERA_DEVICE_GETNEXTVIDEOFRAME returned %d. dwBytes:%d\r\n", f, dwBytes);
pCameracode->fCont = FALSE;
}
}
//
// Stop the stream
//
f = DeviceIoControl ( pCameracode->hCam, IOCTL_CAMERA_DEVICE_STOPVIDEOSTREAM,
0, 0, 0, 0, &dwBytes, NULL);
}
else
{
pCameracode->fCont = FALSE;
}
// Clean up translation code
pCameracode->pMjpe2bmp-> ReleaseDisplayFrame ();
return 0;
}
//----------------------------------------------------------------------
// GetStillImage - Returns a still from the driver
//
int CCameraCode::GetStillImage (WORD wFormat, WORD wFrame, PFORMATPROPS pFmt, PBYTE *ppData, DWORD *pdwSize)
{
int rc = 0;
VIDFORMATSTRUCT vf;
DWORD dwBytes, dwBuff;
BOOL f;
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 (hCam, IOCTL_CAMERA_DEVICE_GETSTILLIMAGE,
&vf, sizeof (VIDFORMATSTRUCT), 0, 0, &dwBytes, NULL);
if (!f)
{
rc = GetLastError();
//printf ("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 (hCam, IOCTL_CAMERA_DEVICE_GETSTILLIMAGE,
&vf, sizeof (VIDFORMATSTRUCT), *ppData, dwBuff, &dwBytes, NULL);
if (!f)
{
rc = GetLastError();
//printf ("failure calling IOCTL_CAMERA_DEVICE_GETSTILLIMAGE rc %d\r\n", rc);
} else
*pdwSize = dwBytes;
//printf ("deviceioctl IOCTL_CAMERA_DEVICE_GETNEXTVIDEOFRAME returned %d. dwBytes:%d\r\n", f, dwBytes);
return rc;
}
//----------------------------------------------------------------------
//
//
int CCameraCode::AllocMMObject (int nSize, PMMOBJSTRUCT obj)
{
if ((obj == 0) || (nSize == 0))
return ERROR_INVALID_PARAMETER;
obj->h = CreateFileMapping ((HANDLE)-1, NULL, PAGE_READWRITE | SEC_COMMIT,
0, nSize, NULL);
if (obj->h == 0)
return GetLastError();
obj->p = (PBYTE)MapViewOfFile (obj->h, FILE_MAP_WRITE, 0, 0, 0);
if (obj->h == 0)
{
CloseHandle (obj->h);
return GetLastError();
}
return 0;
}
//----------------------------------------------------------------------
//
//
int CCameraCode::FreeMMObject (PMMOBJSTRUCT obj)
{
if (obj == 0)
return ERROR_INVALID_PARAMETER;
UnmapViewOfFile (obj->p);
CloseHandle (obj->h);
return 0;
}
//-------------------------------------------------------------------------
// Writes a MJPEG frame as a JPEG file
//
int CCameraCode::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 + -