一个播放摄像头影象的类
// Camera.h: interface for the CCamera class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_CAMERA_H__B5ACFC9D_D275_4114_940F_213B07C494B0__INCLUDED_)
#define AFX_CAMERA_H__B5ACFC9D_D275_4114_940F_213B07C494B0__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "Dshow.h"
#include "amstream.h"
#include "Qedit.h"
class CCamera
{
public:
CCamera();
virtual ~CCamera();
int m_iTotal;
private:
DWORD m_dwReGISter;
IMoniker* m_gVideoMoniker[3]; // This will Access the actual devices
IBaseFilter* m_pSrc[3];
IGraphBuilder* m_pGraph[3];
ICaptureGraphBuilder2* m_pCapture[3];
IVideoWindow* m_pVW[3];
IMediaControl* m_pMc[3];
IBaseFilter* m_pF[3];
ISampleGrabber* m_pGrab[3];
IBaseFilter* m_pNull[3];
HWND m_hCapWnd[3];
public:
BOOL CCameraInit();
BOOL CCameraBindFilter();
// BOOL CCameraFormat();
// BOOL CCameraPreviewWindow();
// BOOL GetPin(IBaseFilter* pFilter, PIN_DIRECTION PinDir, IPin** ppPin);
HRESULT GetUnconnectedPin(IBaseFilter* pFilter, PIN_DIRECTION PinDir, IPin** ppPin);
BOOL ConnectFilters(IGraphBuilder* pGraph, IBaseFilter* pFirst, IBaseFilter* pSecond);
HRESULT AddToRot(IUnknown* pUnkGraph, DWORD* pdwRegister);
void RemoveFromRot(DWORD pdwRegister);
BOOL CCameraGetImage(int i);
// BOOL CCameraSizeImage(CBmpProc* aBmpProc, CRect aRect, CString sFilePath, int nCamera);
BOOL CreteMultileveDir(CString strFilePath);
void MyFreeMediaType(AM_MEDIA_TYPE& mt);
WCHAR* ToWChar(char* str);
};
#endif // !defined(AFX_CAMERA_H__B5ACFC9D_D275_4114_940F_213B07C494B0__INCLUDED_)
// Camera.cpp: implementation of the CCamera class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CameraClientOne.h"
#include "Camera.h"
#include <vfw.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCamera::CCamera()
{
m_iTotal = 0;
for(int i=0; i<1; i++)
{
m_gVideoMoniker[i] = NULL;
m_hCapWnd[i] = NULL;
m_pCapture[i] = NULL;
m_pF[i] = NULL;
m_pGrab[i] = NULL;
m_pMc[i] = NULL;
m_pSrc[i] = NULL;
m_pVW[i] = NULL;
m_pNull[i] = NULL;
// m_bPBmp[i] = (CBmpProc *)new(CBmpProc);
}
}
CCamera::~CCamera()
{
m_iTotal = 0;
for(int i=0; i<m_iTotal; i++)
{
if(m_gVideoMoniker[i])
{
m_gVideoMoniker[i]->Release();
m_gVideoMoniker[i] = NULL;
}
if(m_hCapWnd[i])
{
m_hCapWnd[i] = NULL;
}
if(m_pCapture[i])
{
m_pCapture[i]->Release();
m_pCapture[i] = NULL;
}
if(m_pF[i])
{
m_pF[i]->Release();
m_pF[i] = NULL;
}
if(m_pGrab[i])
{
m_pGrab[i]->Release();
m_pGrab[i] = NULL;
}
if(m_pMc[i])
{
m_pMc[i]->Release();
m_pMc[i] = NULL;
}
if(m_pSrc[i])
{
m_pSrc[i]->Release();
m_pSrc[i] = NULL;
}
if(m_pVW[i])
{
m_pVW[i]->Release();
m_pVW[i] = NULL;
}
if(m_pNull[i])
{
m_pNull[i]->Release();
m_pNull[i] = NULL;
}
// if(&m_bpBmp[i])
// {
// delete (CBmpProc *)m_bpBmp;
// }
}
// Disconnect the connect of GraphEdit and Filter Graph
#ifdef _DEBUG
RemoveFromRot(m_dwRegister);
#endif
}
// return the total of camera
BOOL CCamera::CCameraInit()
{
HRESULT hr;
CoInitialize(NULL);
ICreateDevEnum* pDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC, IID_ICreateDevEnum, (void **)&pDevEnum);
if(FAILED(hr))
{
return false;
}
IEnumMoniker* pClassEnum = NULL;
hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
&pClassEnum, 0);
if(FAILED(hr))
{
return false;
}
pDevEnum->Release();
if(pClassEnum == NULL)
{
return false;
}
pClassEnum->Reset(); // Init pClassEnum.
IMoniker* pMoniker = NULL;
ULONG cFetched;
while (pClassEnum->Next(1, &pMoniker, &cFetched), hr == S_OK) // Get camera device.
{
m_gVideoMoniker[m_iTotal] = pMoniker;
m_iTotal++;
if(m_iTotal == 1)
break;
}
pClassEnum->Release();
return true;
}
// 将其他函数整合到该函数中,目的初始化时显示效果,完成一个Camera初始化
// 即可在Preview中显示。因此不会让用户感觉到太慢。
BOOL CCamera::CCameraBindFilter()
{
HRESULT hr;
// 保存枚举到的视频设备的总数。
int iTempTotal = m_iTotal;
// 因为枚举到的视频设备不一定都可以使用,比如正在使用
// 所以m_iTotal初始化为0,在下面的代码中从新赋值,
// 即使m_iTotal保存可用的视频设备的总数。
m_iTotal = 0;
// 开始按顺序初始化每一个枚举到的视频设备。
for(int i=0; i<iTempTotal; i++){
// 给视频设备榜定source filter.
hr = m_gVideoMoniker[i]->BindToObject(0, 0, IID_IBaseFilter,
(void **)&m_pSrc[i]);
if(FAILED(hr))
{
return false;
}
// 榜定后m_gVideoMoniker指针不再使用。
m_gVideoMoniker[i]->Release();
m_gVideoMoniker[i] = NULL;
// 创造用于管理Filters 的IGraphBuilder。
hr = CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGraph[i]);
if(FAILED(hr))
{
return false;
}
// Display the Filter Graph of this program in GraphEdit when debug.
#ifdef _DEBUG
AddToRot(m_pGraph[i], &m_dwRegister);
#endif
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **)&m_pCapture[i]);
if(FAILED(hr))
{
return false;
}
hr = m_pGraph[i]->QueryInterface(IID_IMediaControl, (LPVOID *)&m_pMc[i]);
if(FAILED(hr))
{
return false;
}
hr = m_pGraph[i]->QueryInterface(IID_IVideoWindow, (LPVOID *)&m_pVW[i]);
if(FAILED(hr))
{
return false;
}
hr = m_pCapture[i]->SetFiltergraph(m_pGraph[i]);
if(FAILED(hr))
{
return false;
}
// Create Sample Grabber.
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (LPVOID *)&m_pF[i]);
if(FAILED(hr))
{
return false;
}
hr = m_pF[i]->QueryInterface(IID_ISampleGrabber, (void **)&m_pGrab[i]);
if(FAILED(hr))
{
return false;
}
//Setting image type for image capture filter.
AM_MEDIA_TYPE amt;
memset(&amt, 0, sizeof(AM_MEDIA_TYPE));
amt.majortype = MEDIATYPE_Video;
amt.subtype = MEDIASUBTYPE_RGB555; // RGB, 16 bit per pixel. Palettized.
hr = m_pGrab[i]->SetMediaType(&amt);
MyFreeMediaType(amt);
hr = m_pGraph[i]->AddFilter(m_pF[i], L"Image Capture");
if(FAILED(hr))
{
return false;
}
hr = m_pGraph[i]->AddFilter(m_pSrc[i], L"Video Capture");
if(FAILED(hr))
{
return false;
}
hr = m_pCapture[i]->RenderStream(&PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Video, m_pSrc[i], NULL, NULL);
if(FAILED(hr))
{
continue;
}
CString sTempTotal;
sTempTotal.Format("%d", i+1);
// AfxGetMainWnd()->GetDlgItem(IDC_STATIC1)->SetWindowText(
// _T("Link camera " + sTempTotal + " ......"));
hr = m_pCapture[i]->RenderStream(&PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Video, m_pSrc[i], NULL, m_pF[i]);
if(FAILED(hr))
{
continue;
}
/*
// Setting source capture filter for the format of image
// and the AvgTimePerFrame.
IAMStreamConfig* pConfig = NULL;
hr = m_pCapture[i]->FindInterface(
&PIN_CATEGORY_CAPTURE,
0, // Any media type.
m_pSrc[i], // Pointer to the capture filter.
IID_IAMStreamConfig,
(void **)&pConfig);
if(SUCCEEDED(hr))
{
AM_MEDIA_TYPE pmtConfig;
hr = m_pGrab[i]->GetConnectedMediaType(&pmtConfig);
if(SUCCEEDED(hr))
{
//pmtConfig.majortype = MEDIATYPE_Video;
//pmtConfig.subtype = MEDIASUBTYPE_RGB555;
/*
// Find the current bit depth.
HDC hdc = GetDC(NULL);
int iBitDepth = GetDeviceCaps(hdc, BITSPIXEL);
ReleaseDC(NULL, hdc);
// Set the media type.
switch(iBitDepth) {
case 8:
pmtConfig.subtype = MEDIASUBTYPE_RGB8;
break;
case 16:
pmtConfig.subtype = MEDIASUBTYPE_RGB555;
break;
case 24:
pmtConfig.subtype = MEDIASUBTYPE_RGB24;
break;
case 32:
pmtConfig.subtype = MEDIASUBTYPE_RGB32;
break;
default:
pmtConfig.subtype = MEDIASUBTYPE_RGB555;
}
*/
/*
VIDEOINFOHEADER* pviImageCapture =
(VIDEOINFOHEADER *)pmtConfig.pbFormat;
pviImageCapture->bmiHeader.biBitCount = 16;
pviImageCapture->bmiHeader.biWidth = 320;
pviImageCapture->bmiHeader.biHeight = 240;
pviImageCapture->AvgTimePerFrame = 333333;
hr = pConfig->SetFormat(&pmtConfig);
//hr = m_pGrab[i]->GetConnectedMediaType(&pmtConfig);
//pviImageCapture = (VIDEOINFOHEADER *)pmtConfig.pbFormat;
MyFreeMediaType(pmtConfig);
}
}
*/
hr = CoCreateInstance(CLSID_NullRenderer, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter,
reintERPret_cast<void **>(&m_pNull[i]));
if(FAILED(hr))
{
return false;
}
hr = m_pGraph[i]->AddFilter(m_pNull[i], L"Null Renderer");
if(FAILED(hr))
{
return false;
}
hr = ConnectFilters(m_pGraph[i], m_pF[i], m_pNull[i]);
if(FAILED(hr))
{
return false;
}
m_pF[i]->Release();
m_pF[i] = NULL;
m_pSrc[i]->Release();
m_pSrc[i] = NULL;
m_pNull[i]->Release();
m_pNull[i] = NULL;
CRect rect;
CWnd* pWnd;
if(i == 0)
pWnd = AfxGetMainWnd()->GetDlgItem(IDC_VIDEO0);
// else if(i == 1)
// pWnd = AfxGetMainWnd()->GetDlgItem(IDC_VIDEO1);
// else if(i == 2)
// pWnd = AfxGetMainWnd()->GetDlgItem(IDC_VIDEO2);
pWnd->GetWindowRect(&rect);
m_hCapWnd[i] = capCreateCaptureWindow(
(LPSTR)"Camera Capture Window",
WS_CHILD|WS_VISIBLE|WS_EX_CLIENTEDGE|
WS_EX_DLGMODALFRAME, 0, 0, rect.Width(),
rect.Width(), pWnd->GetSafeHwnd(), 0
);
m_pVW[i]->put_Owner((OAHWND)m_hCapWnd[i]);
m_pVW[i]->put_Windowstyle(WS_CHILD|WS_VISIBLE|WS_EX_CLIENTEDGE|WS_EX_DLGMODALFRAME);
m_pVW[i]->put_Height(rect.Height());
m_pVW[i]->put_Width(rect.Width());
m_pVW[i]->SetWindowPosition(0, 0,
rect.Width(), rect.Height());
IMediaEventEx *pEvent = NULL;
hr = m_pGraph[i]->QueryInterface(IID_IMediaEventEx, (LPVOID *)&pEvent);
if(FAILED(hr))
{
return false;
}
hr = m_pGrab[i]->SetOneShot(FALSE);
if(FAILED(hr))
{
return false;
}
hr = m_pGrab[i]->SetBufferSamples(TRUE);
if(FAILED(hr))
{
return false;
}
// pEvent->WaitForCompletion(INFINITE, (long *)EC_COMPLETE );
hr = m_pMc[i]->Run();
if(FAILED(hr))
{
return false;
}
m_pMc[i]->Release();
m_pMc[i] = NULL;
m_pVW[i]->Release();
m_pVW[i] = NULL;
m_iTotal++;
}
return true;
}
HRESULT CCamera::GetUnconnectedPin(IBaseFilter* pFilter, PIN_DIRECTION PinDir, IPin** ppPin)
{
*ppPin = 0;
IEnumPins* pEnum = 0;
IPin* pPin = 0;
HRESULT hr = pFilter->EnumPins(&pEnum);
if(FAILED(hr))
return E_FAIL;
pEnum->Reset();
while(pEnum->Next(1, &pPin, 0) == S_OK){
PIN_DIRECTION ThisPinDir;
pPin->QueryDirection(&ThisPinDir);
if (ThisPinDir == PinDir){
IPin* pTmp = 0;
hr = pPin->ConnectedTo(&pTmp);
if(SUCCEEDED(hr)){
pTmp->Release();
}
else{
pEnum->Release();
*ppPin = pPin;
return S_OK;
}
}
pPin->Release();
}
pEnum->Release();
return E_FAIL;
}
BOOL CCamera::ConnectFilters(IGraphBuilder* pGraph, IBaseFilter* pFirst, IBaseFilter* pSecond)
{
IPin* pOut = NULL;
IPin* pIn = NULL;
HRESULT hr;
hr = GetUnconnectedPin(pFirst, PINDIR_OUTPUT, &pOut);
if(FAILED(hr))
return false;
hr = GetUnconnectedPin(pSecond, PINDIR_INPUT, &pIn);
if(FAILED(hr)) {
pOut->Release();
return false;
}
hr = pGraph->Connect(pOut, pIn);
pIn->Release();
pOut->Release();
return true;
}
BOOL CCamera::CCameraGetImage(int i)
{
int iTemp = i;
long lBitmapSize = 0;
HRESULT hr;
hr = m_pGrab[iTemp]->GetCurrentBuffer(&lBitmapSize, NULL);
if(FAILED(hr))
{
return false;
}
char* pBuffer = new char[lBitmapSize];
if(pBuffer == NULL)
{ // new operator failed.
return false;
}
hr = m_pGrab[iTemp]->GetCurrentBuffer(&lBitmapSize,
reinterpret_cast<long *>(pBuffer));
if(FAILED(hr))
{
delete [] pBuffer;
return false;
}
AM_MEDIA_TYPE mt;
hr = m_pGrab[iTemp]->GetConnectedMediaType(&mt);
if(FAILED(hr))
{
delete [] pBuffer;
return false;
}
VIDEOINFOHEADER *pVih;
if ((mt.formattype == FORMAT_VideoInfo) &&
(mt.cbFormat >= sizeof(VIDEOINFOHEADER)) &&
(mt.pbFormat != NULL))
{
pVih = reinterpret_cast<VIDEOINFOHEADER*>(mt.pbFormat);
}
else
{
// Wrong format. Free the format block and return an error.
//AfxMessageBox("Wrong format.");
MyFreeMediaType(mt);
delete [] pBuffer;
//return VFW_E_INVALIDMEDIATYPE; // Something went wrong
return false;
}
// Now pVih->bmiHeader is the BITMAPINFOHEADER for the frame.
CBitmap cBmp;
HBITMAP hBmp;
HWND hWnd = ::GetDesktopWindow();
ASSERT(hWnd);
HDC hDC = ::GetDC(hWnd);
if(hDC == NULL)
{
//AfxMessageBox("GetDC failed.");
return false;
}
int iCurDeVBitPix = GetDeviceCaps(hDC,BITSPIXEL);
int iCurDevPlanes = GetDeviceCaps(hDC,PLANES);
if(cBmp.CreateBitmap(pVih->bmiHeader.biWidth, pVih->bmiHeader.biHeight,
iCurDevPlanes, iCurDevBitPix, NULL) == 0)
{
::ReleaseDC(hWnd, hDC);
delete [] pBuffer;
//AfxMessageBox("CreateBitmap failed.");
return false;
}
hBmp = (HBITMAP)cBmp.Detach();
if(hBmp == NULL)
{
//AfxMessageBox("(HBITMAP)cBmp.Detach failed.");
delete [] pBuffer;
::ReleaseDC(hWnd, hDC);
return false;
}
if(SetDIBits(hDC, hBmp,
0, pVih->bmiHeader.biHeight,
pBuffer,
(BITMAPINFO *)&pVih->bmiHeader,
DIB_RGB_COLORS
) == 0)
{
::DeleteObject(hBmp);
::ReleaseDC(hWnd, hDC);
delete [] pBuffer;
//AfxMessageBox("SetDIBits failed.");
return false;
}
::ReleaseDC(hWnd, hDC);
delete [] pBuffer;
pBuffer = NULL;
if(hBmp == NULL)
{
::DeleteObject(hBmp);
//AfxMessageBox("hBmp is NULL.");
return false;
}
//CBmpProc* aBmpProc = (CBmpProc *)new(CBmpProc);
// if(m_bpBmp[iTemp]->LoadFromHbmp(hBmp) == FALSE)
// {
// //AfxMessageBox("LoadFromHbmp failed!");
// ::DeleteObject(hBmp);
// cBmp.DeleteObject();
// return false;
// }
//m_bpBmp[iTemp] = aBmpProc;
//delete (CBmpProc *)aBmpProc;
::DeleteObject(hBmp);
return true;
}
HRESULT CCamera::AddToRot(IUnknown* pUnkGraph, DWORD* pdwRegister)
{
IMoniker* pMoniker;
IRunningObjectTable* pROT;
if(FAILED(GetRunningObjectTable(0, &pROT))){
return E_FAIL;
}
WCHAR wsz[256];
wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph,
GetCurrentProcessId());
HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
if(SUCCEEDED(hr)){
hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph,
pMoniker, pdwRegister);
pMoniker->Release();
}
pROT->Release();
return hr;
}
void CCamera::RemoveFromRot(DWORD pdwRegister)
{
IRunningObjectTable* pROT;
if(SUCCEEDED(GetRunningObjectTable(0, &pROT))){
pROT->Revoke(pdwRegister);
pROT->Release();
}
}
void CCamera::MyFreeMediaType(AM_MEDIA_TYPE& mt)
{
if (mt.cbFormat != 0)
{
CoTaskMemFree((PVOID)mt.pbFormat);
mt.cbFormat = 0;
mt.pbFormat = NULL;
}
if (mt.pUnk != NULL)
{
// Unecessary because pUnk should not be used, but safest.
mt.pUnk->Release();
mt.pUnk = NULL;
}
}
BOOL CCamera::CreteMultileveDir(CString strFilePath)
{
CString strTempPath = strFilePath;
if (strTempPath.GetAt(strTempPath.GetLength() - 1) != '\\' ) {
strTempPath += '\\';
}
int nCountTemp = 0;
CString strPath = "";
while (1) {
int nCount = strTempPath.Find("\\");
if( nCount != -1 ){
strPath += strTempPath.Mid(nCountTemp, nCount + 2 - nCountTemp);
::CreateDirectory(strPath, NULL);
nCountTemp = nCount + 2;
strTempPath.SetAt(nCount, '|');
strTempPath.SetAt(nCount+1, '|');
}
else
break;
}
return true;
}
/*
void CCamera::CCameraTypeImage(CString aBmpPath, CString aFilePath, CString aImageType)
{
CLSID clImageClsid;
Image* igImageStore;
CString sBmpPath = aBmpPath;
CString sFilePath = aFilePath;
CString sImageType = aImageType;
igImageStore = Image::FromFile(ToWChar(sBmpPath.GetBuffer(255)));
sBmpPath.ReleaseBuffer();
if(sImageType == "jpg"){
GetImageCLSID(L"image/jpeg", &clImageClsid);
}
else if (sImageType == "gif") {
GetImageCLSID(L"image/gif", &clImageClsid);
}
else if (sImageType == "png") {
GetImageCLSID(L"image/png", &clImageClsid);
}
sFilePath = sFilePath + sImageType + "\\0." + sImageType;
igImageStore->Save(ToWChar(sFilePath.GetBuffer(255)), &clImageClsid);
}
*/
WCHAR* CCamera::ToWChar(char* str)
{
static WCHAR buffer[1024];
wcsset(buffer, 0);
MultiByteToWideChar(CP_ACP, 0, str, strlen(str), buffer, 1024);
return buffer;
}
/*
BOOL CCamera::GetImageCLSID(const WCHAR* format, CLSID* pCLSID)
{
UINT num = 0;
UINT size = 0;
ImageCodeInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if (size == 0) {
return false;
}
pImageCodecInfo = (ImageCodecInfo *)(malloc(size));
if(pImageCodecInfo == NULL)
return false;
GetImageEncoders(num, size, pImageCodecInfo);
// Find for the support of format for image in the windows.
for(UINT i=0; i<num; ++i){
// MimeType: Depiction for the program image.
if (wcscmp(pImageCodecInfo[i].MimeType, format) == 0) {
*pCLSID = pImageCodecInfo[i].Clsid;
free(pImageCodecInfo);
return true;
}
}
free(pImageCodecInfo);
return false;
}
*/
/*
UINT CCamera::SendFile(LPVOID lparam, int aImage, int aCamera)
{
CString* sFileName = (CString *)lparam;
CFile cfImageFile;
FILEINFO fiFileInfo;
int x = cfImageFile.Open(*sFileName, CFile::modeRead);
if (x == 0) {
return -1;
}
fiFileInfo.iFileLength = cfImageFile.GetLength();
strcpy(fiFileInfo.cFileName, cfImageFile.GetFileName());
strcpy(fiFileInfo.UserID, gl_sUserID);
fiFileInfo.iCamera = aCamera;
fiFileInfo.iImage = aImage;
}
*/
调用
// TODO: Add extra initialization here
if(m_Camera.CCameraInit() == false)
{
//AfxMessageBox(_T("No found camera!"));
// GetDlgItem(IDC_STATIC1)->SetWindowText(
// _T("Camera愝旛傪尒偮偗傑偣傫丅"));
return false;
}
//GetDlgItem(IDC_STATIC1)->SetWindowText(_T("Link camera......"));
if(m_Camera.CCameraBindFilter() == false)
{
// GetDlgItem(IDC_STATIC1)->SetWindowText(
// _T("Camera愝旛傪尒偮偗傑偣傫丅"));
// //AfxMessageBox(_T("No found camera!"));
return false;
}
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_CAMERA_H__B5ACFC9D_D275_4114_940F_213B07C494B0__INCLUDED_)
#define AFX_CAMERA_H__B5ACFC9D_D275_4114_940F_213B07C494B0__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "Dshow.h"
#include "amstream.h"
#include "Qedit.h"
class CCamera
{
public:
CCamera();
virtual ~CCamera();
int m_iTotal;
private:
DWORD m_dwReGISter;
IMoniker* m_gVideoMoniker[3]; // This will Access the actual devices
IBaseFilter* m_pSrc[3];
IGraphBuilder* m_pGraph[3];
ICaptureGraphBuilder2* m_pCapture[3];
IVideoWindow* m_pVW[3];
IMediaControl* m_pMc[3];
IBaseFilter* m_pF[3];
ISampleGrabber* m_pGrab[3];
IBaseFilter* m_pNull[3];
HWND m_hCapWnd[3];
public:
BOOL CCameraInit();
BOOL CCameraBindFilter();
// BOOL CCameraFormat();
// BOOL CCameraPreviewWindow();
// BOOL GetPin(IBaseFilter* pFilter, PIN_DIRECTION PinDir, IPin** ppPin);
HRESULT GetUnconnectedPin(IBaseFilter* pFilter, PIN_DIRECTION PinDir, IPin** ppPin);
BOOL ConnectFilters(IGraphBuilder* pGraph, IBaseFilter* pFirst, IBaseFilter* pSecond);
HRESULT AddToRot(IUnknown* pUnkGraph, DWORD* pdwRegister);
void RemoveFromRot(DWORD pdwRegister);
BOOL CCameraGetImage(int i);
// BOOL CCameraSizeImage(CBmpProc* aBmpProc, CRect aRect, CString sFilePath, int nCamera);
BOOL CreteMultileveDir(CString strFilePath);
void MyFreeMediaType(AM_MEDIA_TYPE& mt);
WCHAR* ToWChar(char* str);
};
#endif // !defined(AFX_CAMERA_H__B5ACFC9D_D275_4114_940F_213B07C494B0__INCLUDED_)
// Camera.cpp: implementation of the CCamera class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CameraClientOne.h"
#include "Camera.h"
#include <vfw.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCamera::CCamera()
{
m_iTotal = 0;
for(int i=0; i<1; i++)
{
m_gVideoMoniker[i] = NULL;
m_hCapWnd[i] = NULL;
m_pCapture[i] = NULL;
m_pF[i] = NULL;
m_pGrab[i] = NULL;
m_pMc[i] = NULL;
m_pSrc[i] = NULL;
m_pVW[i] = NULL;
m_pNull[i] = NULL;
// m_bPBmp[i] = (CBmpProc *)new(CBmpProc);
}
}
CCamera::~CCamera()
{
m_iTotal = 0;
for(int i=0; i<m_iTotal; i++)
{
if(m_gVideoMoniker[i])
{
m_gVideoMoniker[i]->Release();
m_gVideoMoniker[i] = NULL;
}
if(m_hCapWnd[i])
{
m_hCapWnd[i] = NULL;
}
if(m_pCapture[i])
{
m_pCapture[i]->Release();
m_pCapture[i] = NULL;
}
if(m_pF[i])
{
m_pF[i]->Release();
m_pF[i] = NULL;
}
if(m_pGrab[i])
{
m_pGrab[i]->Release();
m_pGrab[i] = NULL;
}
if(m_pMc[i])
{
m_pMc[i]->Release();
m_pMc[i] = NULL;
}
if(m_pSrc[i])
{
m_pSrc[i]->Release();
m_pSrc[i] = NULL;
}
if(m_pVW[i])
{
m_pVW[i]->Release();
m_pVW[i] = NULL;
}
if(m_pNull[i])
{
m_pNull[i]->Release();
m_pNull[i] = NULL;
}
// if(&m_bpBmp[i])
// {
// delete (CBmpProc *)m_bpBmp;
// }
}
// Disconnect the connect of GraphEdit and Filter Graph
#ifdef _DEBUG
RemoveFromRot(m_dwRegister);
#endif
}
// return the total of camera
BOOL CCamera::CCameraInit()
{
HRESULT hr;
CoInitialize(NULL);
ICreateDevEnum* pDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC, IID_ICreateDevEnum, (void **)&pDevEnum);
if(FAILED(hr))
{
return false;
}
IEnumMoniker* pClassEnum = NULL;
hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
&pClassEnum, 0);
if(FAILED(hr))
{
return false;
}
pDevEnum->Release();
if(pClassEnum == NULL)
{
return false;
}
pClassEnum->Reset(); // Init pClassEnum.
IMoniker* pMoniker = NULL;
ULONG cFetched;
while (pClassEnum->Next(1, &pMoniker, &cFetched), hr == S_OK) // Get camera device.
{
m_gVideoMoniker[m_iTotal] = pMoniker;
m_iTotal++;
if(m_iTotal == 1)
break;
}
pClassEnum->Release();
return true;
}
// 将其他函数整合到该函数中,目的初始化时显示效果,完成一个Camera初始化
// 即可在Preview中显示。因此不会让用户感觉到太慢。
BOOL CCamera::CCameraBindFilter()
{
HRESULT hr;
// 保存枚举到的视频设备的总数。
int iTempTotal = m_iTotal;
// 因为枚举到的视频设备不一定都可以使用,比如正在使用
// 所以m_iTotal初始化为0,在下面的代码中从新赋值,
// 即使m_iTotal保存可用的视频设备的总数。
m_iTotal = 0;
// 开始按顺序初始化每一个枚举到的视频设备。
for(int i=0; i<iTempTotal; i++){
// 给视频设备榜定source filter.
hr = m_gVideoMoniker[i]->BindToObject(0, 0, IID_IBaseFilter,
(void **)&m_pSrc[i]);
if(FAILED(hr))
{
return false;
}
// 榜定后m_gVideoMoniker指针不再使用。
m_gVideoMoniker[i]->Release();
m_gVideoMoniker[i] = NULL;
// 创造用于管理Filters 的IGraphBuilder。
hr = CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGraph[i]);
if(FAILED(hr))
{
return false;
}
// Display the Filter Graph of this program in GraphEdit when debug.
#ifdef _DEBUG
AddToRot(m_pGraph[i], &m_dwRegister);
#endif
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **)&m_pCapture[i]);
if(FAILED(hr))
{
return false;
}
hr = m_pGraph[i]->QueryInterface(IID_IMediaControl, (LPVOID *)&m_pMc[i]);
if(FAILED(hr))
{
return false;
}
hr = m_pGraph[i]->QueryInterface(IID_IVideoWindow, (LPVOID *)&m_pVW[i]);
if(FAILED(hr))
{
return false;
}
hr = m_pCapture[i]->SetFiltergraph(m_pGraph[i]);
if(FAILED(hr))
{
return false;
}
// Create Sample Grabber.
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (LPVOID *)&m_pF[i]);
if(FAILED(hr))
{
return false;
}
hr = m_pF[i]->QueryInterface(IID_ISampleGrabber, (void **)&m_pGrab[i]);
if(FAILED(hr))
{
return false;
}
//Setting image type for image capture filter.
AM_MEDIA_TYPE amt;
memset(&amt, 0, sizeof(AM_MEDIA_TYPE));
amt.majortype = MEDIATYPE_Video;
amt.subtype = MEDIASUBTYPE_RGB555; // RGB, 16 bit per pixel. Palettized.
hr = m_pGrab[i]->SetMediaType(&amt);
MyFreeMediaType(amt);
hr = m_pGraph[i]->AddFilter(m_pF[i], L"Image Capture");
if(FAILED(hr))
{
return false;
}
hr = m_pGraph[i]->AddFilter(m_pSrc[i], L"Video Capture");
if(FAILED(hr))
{
return false;
}
hr = m_pCapture[i]->RenderStream(&PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Video, m_pSrc[i], NULL, NULL);
if(FAILED(hr))
{
continue;
}
CString sTempTotal;
sTempTotal.Format("%d", i+1);
// AfxGetMainWnd()->GetDlgItem(IDC_STATIC1)->SetWindowText(
// _T("Link camera " + sTempTotal + " ......"));
hr = m_pCapture[i]->RenderStream(&PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Video, m_pSrc[i], NULL, m_pF[i]);
if(FAILED(hr))
{
continue;
}
/*
// Setting source capture filter for the format of image
// and the AvgTimePerFrame.
IAMStreamConfig* pConfig = NULL;
hr = m_pCapture[i]->FindInterface(
&PIN_CATEGORY_CAPTURE,
0, // Any media type.
m_pSrc[i], // Pointer to the capture filter.
IID_IAMStreamConfig,
(void **)&pConfig);
if(SUCCEEDED(hr))
{
AM_MEDIA_TYPE pmtConfig;
hr = m_pGrab[i]->GetConnectedMediaType(&pmtConfig);
if(SUCCEEDED(hr))
{
//pmtConfig.majortype = MEDIATYPE_Video;
//pmtConfig.subtype = MEDIASUBTYPE_RGB555;
/*
// Find the current bit depth.
HDC hdc = GetDC(NULL);
int iBitDepth = GetDeviceCaps(hdc, BITSPIXEL);
ReleaseDC(NULL, hdc);
// Set the media type.
switch(iBitDepth) {
case 8:
pmtConfig.subtype = MEDIASUBTYPE_RGB8;
break;
case 16:
pmtConfig.subtype = MEDIASUBTYPE_RGB555;
break;
case 24:
pmtConfig.subtype = MEDIASUBTYPE_RGB24;
break;
case 32:
pmtConfig.subtype = MEDIASUBTYPE_RGB32;
break;
default:
pmtConfig.subtype = MEDIASUBTYPE_RGB555;
}
*/
/*
VIDEOINFOHEADER* pviImageCapture =
(VIDEOINFOHEADER *)pmtConfig.pbFormat;
pviImageCapture->bmiHeader.biBitCount = 16;
pviImageCapture->bmiHeader.biWidth = 320;
pviImageCapture->bmiHeader.biHeight = 240;
pviImageCapture->AvgTimePerFrame = 333333;
hr = pConfig->SetFormat(&pmtConfig);
//hr = m_pGrab[i]->GetConnectedMediaType(&pmtConfig);
//pviImageCapture = (VIDEOINFOHEADER *)pmtConfig.pbFormat;
MyFreeMediaType(pmtConfig);
}
}
*/
hr = CoCreateInstance(CLSID_NullRenderer, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter,
reintERPret_cast<void **>(&m_pNull[i]));
if(FAILED(hr))
{
return false;
}
hr = m_pGraph[i]->AddFilter(m_pNull[i], L"Null Renderer");
if(FAILED(hr))
{
return false;
}
hr = ConnectFilters(m_pGraph[i], m_pF[i], m_pNull[i]);
if(FAILED(hr))
{
return false;
}
m_pF[i]->Release();
m_pF[i] = NULL;
m_pSrc[i]->Release();
m_pSrc[i] = NULL;
m_pNull[i]->Release();
m_pNull[i] = NULL;
CRect rect;
CWnd* pWnd;
if(i == 0)
pWnd = AfxGetMainWnd()->GetDlgItem(IDC_VIDEO0);
// else if(i == 1)
// pWnd = AfxGetMainWnd()->GetDlgItem(IDC_VIDEO1);
// else if(i == 2)
// pWnd = AfxGetMainWnd()->GetDlgItem(IDC_VIDEO2);
pWnd->GetWindowRect(&rect);
m_hCapWnd[i] = capCreateCaptureWindow(
(LPSTR)"Camera Capture Window",
WS_CHILD|WS_VISIBLE|WS_EX_CLIENTEDGE|
WS_EX_DLGMODALFRAME, 0, 0, rect.Width(),
rect.Width(), pWnd->GetSafeHwnd(), 0
);
m_pVW[i]->put_Owner((OAHWND)m_hCapWnd[i]);
m_pVW[i]->put_Windowstyle(WS_CHILD|WS_VISIBLE|WS_EX_CLIENTEDGE|WS_EX_DLGMODALFRAME);
m_pVW[i]->put_Height(rect.Height());
m_pVW[i]->put_Width(rect.Width());
m_pVW[i]->SetWindowPosition(0, 0,
rect.Width(), rect.Height());
IMediaEventEx *pEvent = NULL;
hr = m_pGraph[i]->QueryInterface(IID_IMediaEventEx, (LPVOID *)&pEvent);
if(FAILED(hr))
{
return false;
}
hr = m_pGrab[i]->SetOneShot(FALSE);
if(FAILED(hr))
{
return false;
}
hr = m_pGrab[i]->SetBufferSamples(TRUE);
if(FAILED(hr))
{
return false;
}
// pEvent->WaitForCompletion(INFINITE, (long *)EC_COMPLETE );
hr = m_pMc[i]->Run();
if(FAILED(hr))
{
return false;
}
m_pMc[i]->Release();
m_pMc[i] = NULL;
m_pVW[i]->Release();
m_pVW[i] = NULL;
m_iTotal++;
}
return true;
}
HRESULT CCamera::GetUnconnectedPin(IBaseFilter* pFilter, PIN_DIRECTION PinDir, IPin** ppPin)
{
*ppPin = 0;
IEnumPins* pEnum = 0;
IPin* pPin = 0;
HRESULT hr = pFilter->EnumPins(&pEnum);
if(FAILED(hr))
return E_FAIL;
pEnum->Reset();
while(pEnum->Next(1, &pPin, 0) == S_OK){
PIN_DIRECTION ThisPinDir;
pPin->QueryDirection(&ThisPinDir);
if (ThisPinDir == PinDir){
IPin* pTmp = 0;
hr = pPin->ConnectedTo(&pTmp);
if(SUCCEEDED(hr)){
pTmp->Release();
}
else{
pEnum->Release();
*ppPin = pPin;
return S_OK;
}
}
pPin->Release();
}
pEnum->Release();
return E_FAIL;
}
BOOL CCamera::ConnectFilters(IGraphBuilder* pGraph, IBaseFilter* pFirst, IBaseFilter* pSecond)
{
IPin* pOut = NULL;
IPin* pIn = NULL;
HRESULT hr;
hr = GetUnconnectedPin(pFirst, PINDIR_OUTPUT, &pOut);
if(FAILED(hr))
return false;
hr = GetUnconnectedPin(pSecond, PINDIR_INPUT, &pIn);
if(FAILED(hr)) {
pOut->Release();
return false;
}
hr = pGraph->Connect(pOut, pIn);
pIn->Release();
pOut->Release();
return true;
}
BOOL CCamera::CCameraGetImage(int i)
{
int iTemp = i;
long lBitmapSize = 0;
HRESULT hr;
hr = m_pGrab[iTemp]->GetCurrentBuffer(&lBitmapSize, NULL);
if(FAILED(hr))
{
return false;
}
char* pBuffer = new char[lBitmapSize];
if(pBuffer == NULL)
{ // new operator failed.
return false;
}
hr = m_pGrab[iTemp]->GetCurrentBuffer(&lBitmapSize,
reinterpret_cast<long *>(pBuffer));
if(FAILED(hr))
{
delete [] pBuffer;
return false;
}
AM_MEDIA_TYPE mt;
hr = m_pGrab[iTemp]->GetConnectedMediaType(&mt);
if(FAILED(hr))
{
delete [] pBuffer;
return false;
}
VIDEOINFOHEADER *pVih;
if ((mt.formattype == FORMAT_VideoInfo) &&
(mt.cbFormat >= sizeof(VIDEOINFOHEADER)) &&
(mt.pbFormat != NULL))
{
pVih = reinterpret_cast<VIDEOINFOHEADER*>(mt.pbFormat);
}
else
{
// Wrong format. Free the format block and return an error.
//AfxMessageBox("Wrong format.");
MyFreeMediaType(mt);
delete [] pBuffer;
//return VFW_E_INVALIDMEDIATYPE; // Something went wrong
return false;
}
// Now pVih->bmiHeader is the BITMAPINFOHEADER for the frame.
CBitmap cBmp;
HBITMAP hBmp;
HWND hWnd = ::GetDesktopWindow();
ASSERT(hWnd);
HDC hDC = ::GetDC(hWnd);
if(hDC == NULL)
{
//AfxMessageBox("GetDC failed.");
return false;
}
int iCurDeVBitPix = GetDeviceCaps(hDC,BITSPIXEL);
int iCurDevPlanes = GetDeviceCaps(hDC,PLANES);
if(cBmp.CreateBitmap(pVih->bmiHeader.biWidth, pVih->bmiHeader.biHeight,
iCurDevPlanes, iCurDevBitPix, NULL) == 0)
{
::ReleaseDC(hWnd, hDC);
delete [] pBuffer;
//AfxMessageBox("CreateBitmap failed.");
return false;
}
hBmp = (HBITMAP)cBmp.Detach();
if(hBmp == NULL)
{
//AfxMessageBox("(HBITMAP)cBmp.Detach failed.");
delete [] pBuffer;
::ReleaseDC(hWnd, hDC);
return false;
}
if(SetDIBits(hDC, hBmp,
0, pVih->bmiHeader.biHeight,
pBuffer,
(BITMAPINFO *)&pVih->bmiHeader,
DIB_RGB_COLORS
) == 0)
{
::DeleteObject(hBmp);
::ReleaseDC(hWnd, hDC);
delete [] pBuffer;
//AfxMessageBox("SetDIBits failed.");
return false;
}
::ReleaseDC(hWnd, hDC);
delete [] pBuffer;
pBuffer = NULL;
if(hBmp == NULL)
{
::DeleteObject(hBmp);
//AfxMessageBox("hBmp is NULL.");
return false;
}
//CBmpProc* aBmpProc = (CBmpProc *)new(CBmpProc);
// if(m_bpBmp[iTemp]->LoadFromHbmp(hBmp) == FALSE)
// {
// //AfxMessageBox("LoadFromHbmp failed!");
// ::DeleteObject(hBmp);
// cBmp.DeleteObject();
// return false;
// }
//m_bpBmp[iTemp] = aBmpProc;
//delete (CBmpProc *)aBmpProc;
::DeleteObject(hBmp);
return true;
}
HRESULT CCamera::AddToRot(IUnknown* pUnkGraph, DWORD* pdwRegister)
{
IMoniker* pMoniker;
IRunningObjectTable* pROT;
if(FAILED(GetRunningObjectTable(0, &pROT))){
return E_FAIL;
}
WCHAR wsz[256];
wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph,
GetCurrentProcessId());
HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
if(SUCCEEDED(hr)){
hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph,
pMoniker, pdwRegister);
pMoniker->Release();
}
pROT->Release();
return hr;
}
void CCamera::RemoveFromRot(DWORD pdwRegister)
{
IRunningObjectTable* pROT;
if(SUCCEEDED(GetRunningObjectTable(0, &pROT))){
pROT->Revoke(pdwRegister);
pROT->Release();
}
}
void CCamera::MyFreeMediaType(AM_MEDIA_TYPE& mt)
{
if (mt.cbFormat != 0)
{
CoTaskMemFree((PVOID)mt.pbFormat);
mt.cbFormat = 0;
mt.pbFormat = NULL;
}
if (mt.pUnk != NULL)
{
// Unecessary because pUnk should not be used, but safest.
mt.pUnk->Release();
mt.pUnk = NULL;
}
}
BOOL CCamera::CreteMultileveDir(CString strFilePath)
{
CString strTempPath = strFilePath;
if (strTempPath.GetAt(strTempPath.GetLength() - 1) != '\\' ) {
strTempPath += '\\';
}
int nCountTemp = 0;
CString strPath = "";
while (1) {
int nCount = strTempPath.Find("\\");
if( nCount != -1 ){
strPath += strTempPath.Mid(nCountTemp, nCount + 2 - nCountTemp);
::CreateDirectory(strPath, NULL);
nCountTemp = nCount + 2;
strTempPath.SetAt(nCount, '|');
strTempPath.SetAt(nCount+1, '|');
}
else
break;
}
return true;
}
/*
void CCamera::CCameraTypeImage(CString aBmpPath, CString aFilePath, CString aImageType)
{
CLSID clImageClsid;
Image* igImageStore;
CString sBmpPath = aBmpPath;
CString sFilePath = aFilePath;
CString sImageType = aImageType;
igImageStore = Image::FromFile(ToWChar(sBmpPath.GetBuffer(255)));
sBmpPath.ReleaseBuffer();
if(sImageType == "jpg"){
GetImageCLSID(L"image/jpeg", &clImageClsid);
}
else if (sImageType == "gif") {
GetImageCLSID(L"image/gif", &clImageClsid);
}
else if (sImageType == "png") {
GetImageCLSID(L"image/png", &clImageClsid);
}
sFilePath = sFilePath + sImageType + "\\0." + sImageType;
igImageStore->Save(ToWChar(sFilePath.GetBuffer(255)), &clImageClsid);
}
*/
WCHAR* CCamera::ToWChar(char* str)
{
static WCHAR buffer[1024];
wcsset(buffer, 0);
MultiByteToWideChar(CP_ACP, 0, str, strlen(str), buffer, 1024);
return buffer;
}
/*
BOOL CCamera::GetImageCLSID(const WCHAR* format, CLSID* pCLSID)
{
UINT num = 0;
UINT size = 0;
ImageCodeInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if (size == 0) {
return false;
}
pImageCodecInfo = (ImageCodecInfo *)(malloc(size));
if(pImageCodecInfo == NULL)
return false;
GetImageEncoders(num, size, pImageCodecInfo);
// Find for the support of format for image in the windows.
for(UINT i=0; i<num; ++i){
// MimeType: Depiction for the program image.
if (wcscmp(pImageCodecInfo[i].MimeType, format) == 0) {
*pCLSID = pImageCodecInfo[i].Clsid;
free(pImageCodecInfo);
return true;
}
}
free(pImageCodecInfo);
return false;
}
*/
/*
UINT CCamera::SendFile(LPVOID lparam, int aImage, int aCamera)
{
CString* sFileName = (CString *)lparam;
CFile cfImageFile;
FILEINFO fiFileInfo;
int x = cfImageFile.Open(*sFileName, CFile::modeRead);
if (x == 0) {
return -1;
}
fiFileInfo.iFileLength = cfImageFile.GetLength();
strcpy(fiFileInfo.cFileName, cfImageFile.GetFileName());
strcpy(fiFileInfo.UserID, gl_sUserID);
fiFileInfo.iCamera = aCamera;
fiFileInfo.iImage = aImage;
}
*/
调用
// TODO: Add extra initialization here
if(m_Camera.CCameraInit() == false)
{
//AfxMessageBox(_T("No found camera!"));
// GetDlgItem(IDC_STATIC1)->SetWindowText(
// _T("Camera愝旛傪尒偮偗傑偣傫丅"));
return false;
}
//GetDlgItem(IDC_STATIC1)->SetWindowText(_T("Link camera......"));
if(m_Camera.CCameraBindFilter() == false)
{
// GetDlgItem(IDC_STATIC1)->SetWindowText(
// _T("Camera愝旛傪尒偮偗傑偣傫丅"));
// //AfxMessageBox(_T("No found camera!"));
return false;
}