⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cameracode.cpp

📁 基于WINCE的Webcam程序 基于WINCE的Webcam程序 基于WINCE的Webcam程序 基于WINCE的Webcam程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//----------------------------------------------------------------------
// 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 + -