USB攝像頭採集影象(DirectShow)
攝像頭除了可以捕獲視訊流還可以捕獲單張靜止的圖片,靜止的圖片質量比流的質量要高。支援輸出靜態圖片的攝像頭一般要提供一個靜態圖片PIN,這個PIN的種類是PIN_CATEGORY_STILL。
捕捉靜態圖片常用的filter是Sample Graber filter,它的用法參考手冊。然後將捕捉filter的靜態PIN連線到Sample Grabber,再將Sample Grabber連線到Null Render filter,連線Null Render只是為了給Sample Grabber 的輸出PIN上連線點東西。其結構圖如下所示:
Capture Device ---------------> SampleGraber ---------------------> Null Render
為了實現上圖所示的流圖,需要分別實現其Filter,然後將各個Filter加入Graph,最後將他們連線起來,就實現整個流程。
1.Capture Device 作為採集裝置構建Filter,採用如下程式碼
//將裝置id為deviceId的裝置繫結到指定的pFilter
bool UsbCamera::BindFilter(int deviceId, IBaseFilter **pFilter)
{
if (deviceId < 0)
return false;
CComPtr<ICreateDevEnum> pCreateDevEnum;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void**)&pCreateDevEnum);
if (hr != NOERROR)
return false;
CComPtr<IEnumMoniker> pEm;
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
&pEm, 0);
if (hr != NOERROR)
return false;
pEm->Reset();
ULONG cFetched;
IMoniker *pM;
int index = 0;
while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK, index <= deviceId)
{
IPropertyBag *pBag;
hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
if(SUCCEEDED(hr))
{
VARIANT var;
var.vt = VT_BSTR;
hr = pBag->Read(L"FriendlyName", &var, NULL);
if (hr == NOERROR)
{
if (index == deviceId)
{
pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter);
}
SysFreeString(var.bstrVal);
}
pBag->Release();
}
pM->Release();
index++;
}
return true;
}
2.Sample Graber Filter的實現
加入Sample Graber Filter是為了設定媒體的型別
IBaseFilter* pSampleGrabberFilter;
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (LPVOID *)&pSampleGrabberFilter);
ISampleGrabber* pSampleGrabber;
hr = pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber, (void**)&pSampleGrabber);
//設定媒體型別
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
mt.majortype = MEDIATYPE_Video;
if (mode == "MEDIASUBTYPE_RGB24" )
{
mt.subtype = MEDIASUBTYPE_RGB24;
bytePP = 3.0;
}
else if (mode == "MEDIASUBTYPE_YUY2" )
{
mt.subtype = MEDIASUBTYPE_YUY2;
bytePP = 2.0;
}
mt.formattype = FORMAT_VideoInfo;
hr = pSampleGrabber->SetMediaType(&mt);
3.Null Render Filter的實現
IBaseFilter* pNullFilter;
hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (LPVOID*) &pNullFilter);
4.將各個Filter加入Graph
IGraphBuilder* pGraph;
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **)&pGraph);
pGraph->AddFilter(pDeviceFilter, NULL);
pGraph->AddFilter(pSampleGrabberFilter, L"Grabber");
pGraph->AddFilter(pNullFilter, L"NullRenderer");
5.對於有的採集裝置可能有多個輸入和輸出的PIN,我們需選擇一個通路,通過SetCrossBar裝置;
//對於有多個輸入和輸出的裝置,需選擇一個通路,另外設定媒體型別;
void UsbCamera::SetCrossBar(int fr, int iiw, int iih,string mode)
{
IAMCrossbar *pXBar1 = NULL;
IAMStreamConfig* pVSC = NULL;
HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
(void **)&pBuilder);
if (SUCCEEDED(hr))
hr = pBuilder->SetFiltergraph(pGraph);
hr = pBuilder->FindInterface(&LOOK_UPSTREAM_ONLY, NULL,
pDeviceFilter,IID_IAMCrossbar, (void**)&pXBar1);
if (SUCCEEDED(hr))
{
long OutputPinCount;
long InputPinCount;
long PinIndexRelated;
long PhysicalType;
long inPort = 0;
long outPort = 0;
pXBar1->get_PinCounts(&OutputPinCount,&InputPinCount);
for(int i =0;i<InputPinCount;i++)
{
pXBar1->get_CrossbarPinInfo(TRUE,i,&PinIndexRelated,&PhysicalType);
if(PhysConn_Video_Composite==PhysicalType)
{
inPort = i;
break;
}
}
for(int i =0;i<OutputPinCount;i++)
{
pXBar1->get_CrossbarPinInfo(FALSE,i,&PinIndexRelated,&PhysicalType);
if(PhysConn_Video_VideoDecoder==PhysicalType)
{
outPort = i;
break;
}
}
if(S_OK==pXBar1->CanRoute(outPort,inPort))
{
pXBar1->Route(outPort,inPort);
}
pXBar1->Release();
}
//設定媒體型別;
hr = pBuilder->FindInterface( &PIN_CATEGORY_CAPTURE,0,pDeviceFilter,
IID_IAMStreamConfig,(void**)&pVSC );
AM_MEDIA_TYPE *pmt;
if( SUCCEEDED(hr) )
{
hr = pVSC->GetFormat(&pmt);
if (hr == NOERROR)
{
if (pmt->formattype == FORMAT_VideoInfo )
{
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER*) pmt->pbFormat;
if (mode == "MEDIASUBTYPE_RGB24" )
pmt->subtype = MEDIASUBTYPE_RGB24;
else if (mode == "MEDIASUBTYPE_YUY2" )
pmt->subtype = MEDIASUBTYPE_YUY2;
pvi->AvgTimePerFrame = (LONGLONG)( 10000000 / fr );
pvi->bmiHeader.biWidth = iiw;
pvi->bmiHeader.biHeight = iih;
pvi->bmiHeader.biSizeImage = DIBSIZE(pvi->bmiHeader);
hr = pVSC->SetFormat(pmt);
}
FreeMediaType(*pmt);
}
SAFE_RELEASE( pVSC );
}
}
6.將各filter連線起來
Ipin* pCameraOutput;
Ipin* pGrabberInput;
Ipin* pGrabberOutput;
Ipin* pNullInputPin;
CComPtr<IEnumPins> pEnum;
pDeviceFilter->EnumPins(&pEnum);
hr = pEnum->Reset();
hr = pEnum->Next(1, &pCameraOutput, NULL);
pEnum = NULL;
pSampleGrabberFilter->EnumPins(&pEnum);
pEnum->Reset();
hr = pEnum->Next(1, &pGrabberInput, NULL);
pEnum = NULL;
pSampleGrabberFilter->EnumPins(&pEnum);
pEnum->Reset();
pEnum->Skip(1);
hr = pEnum->Next(1, &pGrabberOutput, NULL);
pEnum = NULL;
pNullFilter->EnumPins(&pEnum);
pEnum->Reset();
hr = pEnum->Next(1, &pNullInputPin, NULL);
//連線Pin;
hr = pGraph->Connect(pCameraOutput, pGrabberInput);
hr = pGraph->Connect(pGrabberOutput, pNullInputPin);
7.執行
pSampleGrabber->SetBufferSamples(TRUE); // true for wait frame done call back 不再另外開闢單幀緩衝區
pSampleGrabber->SetOneShot(TRUE); // FALSE=截圖後繼續執行graph,TRUE=STOP RUN GRAPH
hr = pSampleGrabber->GetConnectedMediaType( &mt );
VIDEOINFOHEADER *videoHeader;
assert(mt.formattype == FORMAT_VideoInfo);
videoHeader = reinterpret_cast<VIDEOINFOHEADER*>(mt.pbFormat);
width = videoHeader->bmiHeader.biWidth;
height = videoHeader->bmiHeader.biHeight;
FreeMediaType(mt);
pMediaControl->Run();
8.原始碼
//==================================ImageBuffer.h================================================================
#ifndef _imagebuffer_h_
#define _imagebuffer_h_
class ImageBuffer
{
public:
enum {
FORMAT_YUV444=0,
FORMAT_YUV422,
FORMAT_YUV411,
FORMAT_RGB,
FORMAT_MONO,
FORMAT_MONO16,
FORMAT_UYV
};
int width;
int height;
int format;
int size;
unsigned char* buffer;
ImageBuffer::ImageBuffer()
{
}
ImageBuffer::ImageBuffer(int width, int height, int format,
unsigned char* buffer, int size)
: width(width), height(height), format(format), buffer(buffer), size(size)
{
}
//static void convert(const ImageBuffer& src, ImageBuffer& dst) throw (RobotsException);
};
#endif
//==================================ImageSource.h================================================================
#ifndef _imagesource_h_
#define _imagesource_h_
#include "ImageBuffer.h"
class ImageSource
{
public:
virtual ImageBuffer getImage() =0;
virtual int getWidth() const=0;
virtual int getHeight() const=0;
};
#endif
//==================================UsbCamera.h================================================================
#ifndef USBCAMER_H_INCLUDE
#define USBCAMER_H_INCLUDE
#include <windows.h>
#include <dshow.h>
#include <atlbase.h>
#include <qedit.h>
#include <string>
#include "ImageSource.h"
#define WIN32_LEAN_AND_MEAN
#ifndef SAFE_RELEASE
#define SAFE_RELEASE( x ) \
if ( NULL != x ) \
{ \
x->Release( ); \
x = NULL; \
}
#endif
using namespace std;
class UsbCamera : public ImageSource
{
public:
UsbCamera();
virtual ~UsbCamera();
virtual ImageBuffer getImage();
virtual int getWidth() const;
virtual int getHeight() const;
static UsbCamera* getCamera( int port = 0, int framerate = 30, int width = 320,
int height = 240, string mode = "" );
static void destroyUsbCamera();
void Init( int deviceId, bool displayProperties = false, int framerate = 30,int iw = 320, int ih = 240, string mode = "" );
void DisplayFilterProperties();
bool BindFilter(int deviceId, IBaseFilter **pFilter);
void SetCrossBar( int fr = 30, int iiw = 320, int iih = 240, string mode = "" );
HRESULT GrabByteFrame();
long GetBufferSize() { return bufferSize; }
long* GetBuffer() { return pBuffer; }
BYTE* GetByteBuffer() { return pBYTEbuffer;}
public:
bool bisValid;
protected:
IGraphBuilder* pGraph;
IBaseFilter* pDeviceFilter;
IMediaControl* pMediaControl;
IBaseFilter* pSampleGrabberFilter;
ISampleGrabber* pSampleGrabber;
IPin* pGrabberInput;
IPin* pGrabberOutput;
IPin* pCameraOutput;
IMediaEvent* pMediaEvent;
IBaseFilter* pNullFilter;
IPin* pNullInputPin;
ICaptureGraphBuilder2* pBuilder;
static UsbCamera* m_camera;
ImageBuffer imagebuf;
double bytePP;
private:
void ErrMsg(LPTSTR szFormat,...);
void FreeMediaType(AM_MEDIA_TYPE& mt);
long bufferSize;
long* pBuffer;
BYTE* pBYTEbuffer;
bool connected;
int width;
int height;
ImageBuffer m_buffer;
bool bnotify;
string format_mode;
};
#endif
//==================================UsbCamera.cpp================================================================
#include "StdAfx.h"
#include <assert.h>
#include "UsbCamera.h"
#ifndef USE_YUV422_FORMAT
#define USE_YUV422_FORMAT 0
#endif
#ifndef USE_RGB24_FORMAT
#define USE_RGB24_FORMAT 1
#endif
#ifndef SEND_WORK_STATE
#define SEND_WORK_STATE 0
#endif
UsbCamera* UsbCamera::m_camera = NULL;
UsbCamera::UsbCamera():bisValid(false),pBuffer(NULL),pBYTEbuffer(NULL),bufferSize(0),bytePP(2.0),
connected(false),bnotify(false),width(0),height(0)
{
if (FAILED(CoInitialize(NULL)))
{
return;
}
pGraph = NULL;
pDeviceFilter = NULL;
pMediaControl = NULL;
pSampleGrabberFilter = NULL;
pSampleGrabber = NULL;
pGrabberInput = NULL;
pGrabberOutput = NULL;
pCameraOutput = NULL;
pMediaEvent = NULL;
pNullFilter = NULL;
pNullInputPin = NULL;
pBuilder = NULL;
}
UsbCamera::~UsbCamera()
{
if( connected )
{
if (pMediaControl )
{
pMediaControl->Stop();
}
SAFE_RELEASE(pGraph);
SAFE_RELEASE(pDeviceFilter);
SAFE_RELEASE(pMediaControl);
SAFE_RELEASE(pSampleGrabberFilter);
SAFE_RELEASE(pSampleGrabber);
SAFE_RELEASE(pGrabberInput);
SAFE_RELEASE(pGrabberOutput);
SAFE_RELEASE(pCameraOutput);
SAFE_RELEASE(pMediaEvent);
SAFE_RELEASE(pNullFilter);
SAFE_RELEASE(pNullInputPin);
SAFE_RELEASE(pBuilder);
CoUninitialize();
}
if( pBuffer )
delete[] pBuffer;
if( pBYTEbuffer )
delete[] pBYTEbuffer;
}
void UsbCamera::Init(int deviceId, bool displayProperties,
int framerate, int iw , int ih, string mode )
{
HRESULT hr = S_OK;
format_mode = mode;
// Create the Filter Graph Manager.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **)&pGraph);
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (LPVOID *)&pSampleGrabberFilter);
hr = pGraph->QueryInterface(IID_IMediaControl, (void **) &pMediaControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **) &pMediaEvent);
hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (LPVOID*) &pNullFilter);
hr = pGraph->AddFilter(pNullFilter, L"NullRenderer");
hr = pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber, (void**)&pSampleGrabber);
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
mt.majortype = MEDIATYPE_Video;
if (mode == "MEDIASUBTYPE_RGB24" )
{
mt.subtype = MEDIASUBTYPE_RGB24;
bytePP = 3.0;
}
else if (mode == "MEDIASUBTYPE_YUY2" )
{
mt.subtype = MEDIASUBTYPE_YUY2;
bytePP = 2.0;
}
mt.formattype = FORMAT_VideoInfo;
hr = pSampleGrabber->SetMediaType(&mt);
pGraph->AddFilter(pSampleGrabberFilter, L"Grabber");
// Bind Device Filter. We know the device because the id was passed in
if(!BindFilter(deviceId, &pDeviceFilter))
{
ErrMsg(TEXT("未找到USB攝像頭!\n請檢查裝置後重試!"));
exit(0);
return;
}
pGraph->AddFilter(pDeviceFilter, NULL);
CComPtr<IEnumPins> pEnum;
pDeviceFilter->EnumPins(&pEnum);
hr = pEnum->Reset();
hr = pEnum->Next(1, &pCameraOutput, NULL);
pEnum = NULL;
pSampleGrabberFilter->EnumPins(&pEnum);
pEnum->Reset();
hr = pEnum->Next(1, &pGrabberInput, NULL);
pEnum = NULL;
pSampleGrabberFilter->EnumPins(&pEnum);
pEnum->Reset();
pEnum->Skip(1);
hr = pEnum->Next(1, &pGrabberOutput, NULL);
pEnum = NULL;
pNullFilter->EnumPins(&pEnum);
pEnum->Reset();
hr = pEnum->Next(1, &pNullInputPin, NULL);
SetCrossBar(framerate,iw,ih,mode);
if (displayProperties)
{
CComPtr<ISpecifyPropertyPages> pPages;
HRESULT hr = pCameraOutput->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pPages);
if (SUCCEEDED(hr))
{
PIN_INFO PinInfo;
pCameraOutput->QueryPinInfo(&PinInfo);
CAUUID caGUID;
pPages->GetPages(&caGUID);
OleCreatePropertyFrame( NULL,0, 0,L"Property Sheet",1,
(IUnknown **)&(pCameraOutput),
caGUID.cElems, caGUID.pElems,
0,0,NULL );
CoTaskMemFree(caGUID.pElems);
PinInfo.pFilter->Release();
}
}
hr = pGraph->Connect(pCameraOutput, pGrabberInput);
hr = pGraph->Connect(pGrabberOutput, pNullInputPin);
pSampleGrabber->SetBufferSamples(TRUE); // true for wait frame done call back 不再另外開闢單幀緩衝區
pSampleGrabber->SetOneShot(TRUE); // FALSE=截圖後繼續執行graph,TRUE=STOP RUN GRAPH
hr = pSampleGrabber->GetConnectedMediaType( &mt );
VIDEOINFOHEADER *videoHeader;
assert(mt.formattype == FORMAT_VideoInfo);
videoHeader = reinterpret_cast<VIDEOINFOHEADER*>(mt.pbFormat);
width = videoHeader->bmiHeader.biWidth;
height = videoHeader->bmiHeader.biHeight;
FreeMediaType(mt);
pMediaControl->Run();
connected = true;
}
//將裝置id為deviceId的裝置 繫結到指定的pFilter
bool UsbCamera::BindFilter(int deviceId, IBaseFilter **pFilter)
{
if (deviceId < 0)
return false;
CComPtr<ICreateDevEnum> pCreateDevEnum;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void**)&pCreateDevEnum);
if (hr != NOERROR)
return false;
CComPtr<IEnumMoniker> pEm;
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
&pEm, 0);
if (hr != NOERROR)
return false;
pEm->Reset();
ULONG cFetched;
IMoniker *pM;
int index = 0;
while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK, index <= deviceId)
{
IPropertyBag *pBag;
hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
if(SUCCEEDED(hr))
{
VARIANT var;
var.vt = VT_BSTR;
hr = pBag->Read(L"FriendlyName", &var, NULL);
if (hr == NOERROR)
{
if (index == deviceId)
{
pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter);
}
SysFreeString(var.bstrVal);
}
pBag->Release();
}
pM->Release();
index++;
}
return true;
}
//對於有多個輸入和輸出的裝置,需選擇一個通路,另外設定媒體型別;
void UsbCamera::SetCrossBar(int fr, int iiw, int iih,string mode)
{
IAMCrossbar *pXBar1 = NULL;
IAMStreamConfig* pVSC = NULL;
HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
(void **)&pBuilder);
if (SUCCEEDED(hr))
hr = pBuilder->SetFiltergraph(pGraph);
hr = pBuilder->FindInterface(&LOOK_UPSTREAM_ONLY, NULL,
pDeviceFilter,IID_IAMCrossbar, (void**)&pXBar1);
if (SUCCEEDED(hr))
{
long OutputPinCount;
long InputPinCount;
long PinIndexRelated;
long PhysicalType;
long inPort = 0;
long outPort = 0;
pXBar1->get_PinCounts(&OutputPinCount,&InputPinCount);
for(int i =0;i<InputPinCount;i++)
{
pXBar1->get_CrossbarPinInfo(TRUE,i,&PinIndexRelated,&PhysicalType);
if(PhysConn_Video_Composite==PhysicalType)
{
inPort = i;
break;
}
}
for(int i =0;i<OutputPinCount;i++)
{
pXBar1->get_CrossbarPinInfo(FALSE,i,&PinIndexRelated,&PhysicalType);
if(PhysConn_Video_VideoDecoder==PhysicalType)
{
outPort = i;
break;
}
}
if(S_OK==pXBar1->CanRoute(outPort,inPort))
{
pXBar1->Route(outPort,inPort);
}
pXBar1->Release();
}
//設定媒體型別;
hr = pBuilder->FindInterface( &PIN_CATEGORY_CAPTURE,0,pDeviceFilter,
IID_IAMStreamConfig,(void**)&pVSC );
AM_MEDIA_TYPE *pmt;
if( SUCCEEDED(hr) )
{
hr = pVSC->GetFormat(&pmt);
if (hr == NOERROR)
{
if (pmt->formattype == FORMAT_VideoInfo )
{
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER*) pmt->pbFormat;
if (mode == "MEDIASUBTYPE_RGB24" )
pmt->subtype = MEDIASUBTYPE_RGB24;
else if (mode == "MEDIASUBTYPE_YUY2" )
pmt->subtype = MEDIASUBTYPE_YUY2;
pvi->AvgTimePerFrame = (LONGLONG)( 10000000 / fr );
pvi->bmiHeader.biWidth = iiw;
pvi->bmiHeader.biHeight = iih;
pvi->bmiHeader.biSizeImage = DIBSIZE(pvi->bmiHeader);
hr = pVSC->SetFormat(pmt);
}
FreeMediaType(*pmt);
}
SAFE_RELEASE( pVSC );
}
}
HRESULT UsbCamera::GrabByteFrame()
{
HRESULT hr;
long size = 0;
long evCode;
hr = pMediaEvent->WaitForCompletion(10e4, &evCode); // INFINITE
#if SEND_WORK_STATE
if( evCode == EC_COMPLETE )
pMediaControl->Pause();
else if( FAILED(hr) || evCode <= 0 )
{
if( !bnotify )
{
bnotify = true;
bisValid = false;
return E_FAIL;
}
}
#endif
pSampleGrabber->GetCurrentBuffer(&size, NULL);
// use YUV422 format
#if USE_YUV422_FORMAT
// if buffer is not the same size as before, create a new one
if( size != bufferSize )
{
if( pBuffer )
delete[] pBuffer;
bufferSize = size;
pBuffer = new long[bufferSize];
if( pBYTEbuffer )
delete[] pBYTEbuffer;
pBYTEbuffer = new BYTE[bufferSize*2];
memset(pBYTEbuffer,0,sizeof(BYTE)*bufferSize*2);
}
pSampleGrabber->GetCurrentBuffer(&size, pBuffer);
const BYTE* pSrc = (BYTE*) pBuffer;
const BYTE* pSrcEnd = pSrc + (width*height*2);
BYTE* pDest = pBYTEbuffer;
while (pSrc < pSrcEnd)
{
for (register int i =0; i< width; i++)
{
BYTE temp = *(pSrc++);
BYTE temp2 = *(pSrc++);
*(pDest++) = temp2;
*(pDest++) = temp;
}
}
#endif
#if USE_RGB24_FORMAT
// use RGB format
if (size != bufferSize)
{
if (pBuffer)
delete[] pBuffer;
bufferSize = size;
pBuffer = new long[bufferSize];
if(pBYTEbuffer)
delete[] pBYTEbuffer;
pBYTEbuffer = new BYTE[bufferSize*3];
}
pSampleGrabber->GetCurrentBuffer(&size, pBuffer);
BYTE* pDest = pBYTEbuffer;
BYTE *pBYTETemp = pBYTEbuffer;
const BYTE* pSrc = (BYTE*) pBuffer;
const ULONG remainder = ((width*3+3) & ~3) - width*3;
for (register unsigned int i = 0; i < height; i++ )
{
pDest = pBYTETemp + (height-i) * width * 3;
for (register unsigned int j = 0; j < width; j++ )
{
const BYTE blue = *(pSrc++);
const BYTE green = *(pSrc++);
const BYTE red = *(pSrc++);
*(pDest++) = red;
*(pDest++) = green;
*(pDest++) = blue;
pDest += remainder;
}
}
#endif
return S_OK;
}
ImageBuffer UsbCamera::getImage()
{
HRESULT hr = S_OK;
hr = GrabByteFrame();
if(FAILED(hr))
ErrMsg(TEXT("UsbCamera disconnect!"));
const BYTE* pSrc = GetByteBuffer();
#if USE_YUV422_FORMAT
m_buffer = ImageBuffer( width,height,ImageBuffer::FORMAT_YUV422,
(unsigned char*)pSrc,(int)(width*height*2.));
#endif
#if USE_RGB24_FORMAT
m_buffer = ImageBuffer( width,height,ImageBuffer::FORMAT_RGB,
(unsigned char*)pSrc,(int)(width*height*3.));
#endif
pMediaControl->Run();
return m_buffer;
}
UsbCamera* UsbCamera::getCamera(int port, int framerate /* = 30 */, int width /* = 320 */,
int height /* = 240 */,string mode)
{
if (m_camera == NULL)
{
m_camera = new UsbCamera();
m_camera->Init(port,false,framerate,width,height,mode);
m_camera->bisValid = true;
}
return m_camera;
}
void UsbCamera::destroyUsbCamera()
{
if (m_camera)
{
delete m_camera;
m_camera = NULL;
}
}
void UsbCamera::FreeMediaType(AM_MEDIA_TYPE& mt)
{
if (mt.cbFormat != 0)
{
CoTaskMemFree((PVOID)mt.pbFormat);
mt.cbFormat = 0;
mt.pbFormat = NULL;
}
if (mt.pUnk != NULL)
{
mt.pUnk->Release();
mt.pUnk = NULL;
}
}
int UsbCamera::getWidth() const
{
return width;
}
int UsbCamera::getHeight() const
{
return height;
}
void UsbCamera::ErrMsg(LPTSTR szFormat,...)
{
static TCHAR szBuffer[2048]={0};
const size_t NUMCHARS = sizeof(szBuffer) / sizeof(szBuffer[0]);
const int LASTCHAR = NUMCHARS - 1;
va_list pArgs;
va_start(pArgs, szFormat);
_vsntprintf(szBuffer, NUMCHARS - 1, szFormat, pArgs);
va_end(pArgs);
szBuffer[LASTCHAR] = TEXT('\0');
///MessageBox(NULL, szBuffer, "UsbCamera Error",
// MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
}
void UsbCamera::DisplayFilterProperties()
{
ISpecifyPropertyPages* pProp;
HRESULT hr = pDeviceFilter->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pProp);
if (SUCCEEDED(hr))
{
FILTER_INFO FilterInfo;
hr = pDeviceFilter->QueryFilterInfo(&FilterInfo);
IUnknown* pFilterUnk;
pDeviceFilter->QueryInterface(IID_IUnknown,(void**)&pFilterUnk);
CAUUID caGUID;
pProp->GetPages(&caGUID);
pProp->Release();
OleCreatePropertyFrame(
NULL,
0,
0,
FilterInfo.achName,
1,
&pFilterUnk,
caGUID.cElems,
caGUID.pElems,
0,
0,
NULL);
pFilterUnk->Release();
FilterInfo.pGraph->Release();
CoTaskMemFree(caGUID.pElems);
}
}
//==========================================main.cpp===========================================
#include "UsbCamera.h"
int main(int argc, char** argv)
{
cvNamedWindow( "Motion", 1 );
UsbCamera* pCamera = UsbCamera::getCamera(0,30,480,240,"MEDIASUBTYPE_RGB24");
if(NULL == pCamera)
{
return 0;
}
ImageBuffer buffer = pCamera->getImage();
IplImage* pImage = cvCreateImage(cvSize(buffer.width,buffer.height),8,3);
for(;;)
{
buffer = pCamera->getImage();
for(int i=0;i<pImage->height;i++)
{
uchar* data=(uchar*)pImage->imageData + pImage->widthStep * i;
for(int j=0;j<pImage->width;j++)
{
data[3*j] = buffer.buffer[3*(i*buffer.width+j)+2];
data[3*j+1] = buffer.buffer[3*(i*buffer.width+j)+1];
data[3*j+2] = buffer.buffer[3*(i*buffer.width+j)+0];
}
}
cvShowImage( "Motion", pImage );
if( cvWaitKey(10) >= 0 )
break;
}
return 0;
}