| ARToolKit | Mailing List Archive |  
					  					
				 |  
 
			
| From: | Gerhard Reitmayr <reitmayr@i ...............> | Received: | Jan 18, 2002 | 
| To | artoolkit <artoolkit@h ..................> | ||
| Subject: | Some more mods to ARFrameGrabber :) | ||
This is a multi-part message in MIME format.
--------------030709010201000802050902
Content-Type: 
Content-Transfer-Encoding: 8bit
Hi,
I added the ability to define a video image size during initialization. 
It simlpy sets the first media type it finds that fits the desired 
format. If none is found, it doesn't change the default format. In any 
case there are to member functions that let you query the size of the 
video image.
maybe somebody finds this useful. please use the changes as you like.
bye,
   Gerhard
-- 
Gerhard Reitmayr  mailto:reitmayr@i ...............
                   tel:++ 43 1 58801 18856
Interactive Media Systems Group
Vienna University of Technology
--------------030709010201000802050902
Content-Type: text/plain; charset=windows-1252;
 name="ARFrameG.h"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ARFrameG.h"
// ARFrameGrabber.h: interface for the ARFrameGrabber class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_ARFRAMEGRABBER_H__C5553937_4BAB_4FEF_B4A6_1693AB0C99E3__INCLUDED_)
#define AFX_ARFRAMEGRABBER_H__C5553937_4BAB_4FEF_B4A6_1693AB0C99E3__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <dshow.h>
//#include <streams.h>
#include <atlbase.h>
#include <qedit.h>
class SmartString
{
public:
	SmartString():str(NULL) {}
	SmartString(char* pStr):str(NULL)
	{
		if (pStr)
		{
			int size = strlen(pStr);
			str = new char[size+1];
			strcpy(str, pStr);
		}
	}
	SmartString(SmartString& sStr)
	{
		SetString(sStr.GetBuffer());
	}
	~SmartString()
	{
		if (str)
			delete[] str;
	}
	SmartString& operator =(char* pStr)
	{
		SetString(pStr);
		return *this;
	}
	SmartString& operator =(SmartString& sStr)
	{
		SetString(sStr.GetBuffer());
		return *this;
	}
	char* GetBuffer() {return str;}
protected:
	void SetString(char *pStr)
	{
		if (str)
			delete[] str;
		if (!pStr)
		{
			str = NULL;
		}
		else
		{
			int size = strlen(pStr);
			str = new char[size + 1];
			strcpy(str, pStr);
		}
	}
	char* str;
};
struct DeviceInfo
{
	DeviceInfo():next(NULL), deviceId(-1)
	{
	} 
	~DeviceInfo()
	{
		if (next)
			delete next;
	}
	SmartString friendlyName;
	int			deviceId;	
	DeviceInfo* next;
};
class ARFrameGrabber  
{
public:
	ARFrameGrabber();
	virtual ~ARFrameGrabber();
	void Init(int deviceId, int = 0, int = 0);
	void BindFilter(int deviceId, IBaseFilter **pFilter);
	void GrabFrame(long* size, long** pBuffer);
	void GrabFrame();
	void Grab32BitFrame();
	long  GetBufferSize() {return bufferSize;}
	long* GetBuffer() {return pBuffer;}
	
	void SetFlippedImageHorizontal(bool flag) {flipImageH = flag;}
    void SetFlippedImageVertical(bool flag) {flipImageV = flag;}
    void SetFlippedImage(bool flag) {flipImageV =flag; flipImageH = flag;}
	void DisplayProperties();
	void EnumDevices(DeviceInfo *head);
    int  GetWidth() { return width; }
    int  GetHeight() { return height; }
protected:
	CComPtr<IGraphBuilder> pGraph;
	CComPtr<IBaseFilter> pDeviceFilter;
	CComPtr<IMediaControl> pMediaControl;
	CComPtr<IBaseFilter> pSampleGrabberFilter;
	CComPtr<ISampleGrabber> pSampleGrabber;
	CComPtr<IPin> pGrabberInput;
	CComPtr<IPin> pGrabberOutput;
	CComPtr<IPin> pCameraOutput;
	CComPtr<IMediaEvent> pMediaEvent;
	CComPtr<IBaseFilter> pNullFilter;
	CComPtr<IPin> pNullInputPin;    
	void FlipImage(long* pBuf);
private:
	void ReportError(char *msg);
    int  width;
    int  height;
	bool flipImageH;
    bool flipImageV;
	long bufferSize;
	long *pBuffer;
};
#endif // !defined(AFX_ARFRAMEGRABBER_H__C5553937_4BAB_4FEF_B4A6_1693AB0C99E3__INCLUDED_)
--------------030709010201000802050902
Content-Type: text/plain; charset=windows-1252;
 name="ARFrameG.cpp"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ARFrameG.cpp"
// ARFrameGrabber.cpp: implementation of the ARFrameGrabber class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ARFrameGrabber.h"
void WINAPI DeleteMediaType(AM_MEDIA_TYPE *pmt);
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
ARFrameGrabber::ARFrameGrabber():pBuffer(NULL), bufferSize(0), flipImageV(false), flipImageH(false)
{
}
ARFrameGrabber::~ARFrameGrabber()
{
	pMediaControl->Stop();
}
void ARFrameGrabber::Init(int deviceId, int width_, int height_)
{
	HRESULT hr = S_OK;
	// 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;
	mt.subtype = MEDIASUBTYPE_RGB32;
	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
	BindFilter(deviceId, &pDeviceFilter);
	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);
	// Set the grabbing size
    // First we iterate through the available media types and 
    // store the first one that fits the requested size.
    // If we have found one, we set it.
    // In any case we query the size of the current media type
    // to have this information for clients of this class.
    //     Gerhard Reitmayr <reitmayr@i ...............>
    CComPtr<IAMStreamConfig> pConfig;
    IEnumMediaTypes *pMedia;
    AM_MEDIA_TYPE *pmt = NULL, *pfnt = NULL;
    hr = pCameraOutput->EnumMediaTypes( &pMedia );
    if(SUCCEEDED(hr))
    {
        while(pMedia->Next(1, &pmt, 0) == S_OK)
        {
            if( pmt->formattype == FORMAT_VideoInfo )
            {
                VIDEOINFOHEADER *vih = (VIDEOINFOHEADER *)pmt->pbFormat;
                // printf("Size %i  %i\n", vih->bmiHeader.biWidth, vih->bmiHeader.biHeight );
                if( vih->bmiHeader.biWidth == width_ && vih->bmiHeader.biHeight == height_ )
                {
                    pfnt = pmt;
                    // printf("found mediatype with %i %i\n", vih->bmiHeader.biWidth, vih->bmiHeader.biHeight );
                    break;
                }
                DeleteMediaType( pmt );
                //delete pmt;
            }                        
        }
        pMedia->Release();
    }
    hr = pCameraOutput->QueryInterface( IID_IAMStreamConfig, (void **) &pConfig );
    if(SUCCEEDED(hr))
    {
        if( pfnt != NULL )
        {
            pConfig->SetFormat( pfnt );
            DeleteMediaType( pfnt );
            //delete pfnt;
        }
        hr = pConfig->GetFormat( &pfnt );
        if(SUCCEEDED(hr))
        {
            width = ((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biWidth;
            height = ((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biHeight;
        }
    }
    
	hr = pGraph->Connect(pCameraOutput, pGrabberInput);
	hr = pGraph->Connect(pGrabberOutput, pNullInputPin);
//	hr = pGraph->Render(pGrabberOutput);
	if (FAILED(hr))
	{
		switch(hr)
		{
		case VFW_S_NOPREVIEWPIN :
			break;
		case E_FAIL :
			break;
		case E_INVALIDARG :
			break;
		case E_POINTER :
			break;
		}
	}
	pSampleGrabber->SetBufferSamples(TRUE);
	pSampleGrabber->SetOneShot(TRUE);
}
void ARFrameGrabber::GrabFrame(long* size, long** pBuffer)
{
	if (!size)
		return;
	// don't want to leak mem, pBuffer must be NULL
	if (!pBuffer || *pBuffer)
		return;
	long evCode;
	pMediaControl->Run();
	pMediaEvent->WaitForCompletion(INFINITE, &evCode);
	pSampleGrabber->GetCurrentBuffer(size, NULL);
	if (*size)
	{
		*pBuffer = new long[*size];
	}
	pSampleGrabber->GetCurrentBuffer(size, *pBuffer);
}
void ARFrameGrabber::GrabFrame()
{
	long evCode;
	long size = 0;
	pMediaControl->Run();
	pMediaEvent->WaitForCompletion(INFINITE, &evCode);
	pSampleGrabber->GetCurrentBuffer(&size, NULL);
	// 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];
	}
	pSampleGrabber->GetCurrentBuffer(&size, pBuffer);
	if (flipImageV | flipImageH)
		FlipImage(pBuffer);
}
void ARFrameGrabber::FlipImage(long* pBuf)
{
	DWORD *ptr = (DWORD*)pBuf;
	int pixelCount = bufferSize/4;
 
	if (!pBuf)
		return;
    // Added code for more image manipulations
    // Gerhard Reitmayr <reitmayr@i ...............
    if( flipImageV )
    {
        if( flipImageH )
        {
            // both flips set -> rotation about 180 degree
	        for (int index = 0; index < pixelCount/2; index++)
	        {
		        ptr[index] = ptr[index] ^ ptr[pixelCount - index - 1];
		        ptr[pixelCount - index - 1] = ptr[index] ^ ptr[pixelCount - index - 1];
		        ptr[index] = ptr[index] ^ ptr[pixelCount - index - 1];
	        }
        } 
        else  
        {
            // only vertical flip 
            for( int line = 0; line < height/2; line++ )
                for( int pixel = 0; pixel < width; pixel ++ )
                {
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[pixelCount - line*width - (width - pixel )];
                    ptr[pixelCount - line*width - (width - pixel )] = ptr[line*width+pixel] ^ ptr[pixelCount - line*width - (width - pixel )];
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[pixelCount - line*width - (width - pixel )];
                }
        }
    }
    else 
    {
        if( flipImageH )
        {
            // only horizontal flip
            for( int line = 0; line < height; line++ )
                for( int pixel = 0; pixel < width/2; pixel ++ )
                {
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[line*width + (width - pixel )];
                    ptr[line*width + (width - pixel )] = ptr[line*width+pixel] ^ ptr[line*width + (width - pixel )];
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[line*width + (width - pixel )];
                }
        }
    }
}
void ARFrameGrabber::Grab32BitFrame()
{
	long evCode;
	long size = 0;
	long* pData;
	unsigned char* pTemp;
	unsigned char* ptr;
	pMediaControl->Run();
	pMediaEvent->WaitForCompletion(INFINITE, &evCode);
	pSampleGrabber->GetCurrentBuffer(&size, NULL);
	if (size != bufferSize)
	{
		if (pBuffer)
			delete[] pBuffer;
		bufferSize = size/3*4;  // add space for padding
		pBuffer = new long[bufferSize];
	}
	pData= (long*) new unsigned char[size];
	pSampleGrabber->GetCurrentBuffer(&size, pData);
	ptr = ((unsigned char*)pBuffer) + bufferSize - 1;
	pTemp = (unsigned char*) pData;
	// do the padding
	for (int index = 0; index < size/3; index++)
	{
		unsigned char r = *(pTemp++);
		unsigned char g = *(pTemp++);
		unsigned char b = *(pTemp++);
		*(ptr--) = 0;
		*(ptr--) = b;
		*(ptr--) = g;
		*(ptr--) = r;
	}
/*
	for (int index = 0; index < size; index++)
	{
		*ptr = ((unsigned char *)pTemp)[index];
		ptr--;
		if (index % 3 == 2)
		{
			*ptr = 0;
			ptr--;
		}
	}
*/
	delete[] pData;
}
void ARFrameGrabber::BindFilter(int deviceId, IBaseFilter **pFilter)
{
	if (deviceId < 0)
		return;
	
    // enumerate all video capture devices
	CComPtr<ICreateDevEnum> pCreateDevEnum;
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
			  IID_ICreateDevEnum, (void**)&pCreateDevEnum);
    if (hr != NOERROR)
	{
//		ErrMsg("Error Creating Device Enumerator");
		return;
	}
    CComPtr<IEnumMoniker> pEm;
    hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
								&pEm, 0);
    if (hr != NOERROR) 
	{
//		ErrMsg("Sorry, you have no video capture hardware");
		return;
    }
    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++;
    }
}
void ARFrameGrabber::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.p),
			caGUID.cElems,
			caGUID.pElems,
			0,
			0,
			NULL);
		CoTaskMemFree(caGUID.pElems);
		PinInfo.pFilter->Release();
	}
}
void ARFrameGrabber::EnumDevices(DeviceInfo *head)
{
	if (!head)
		return;
	DeviceInfo *ptr = head;
	int id = 0;
	
    // enumerate all video capture devices
	CComPtr<ICreateDevEnum> pCreateDevEnum;
//    ICreateDevEnum *pCreateDevEnum;
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
			  IID_ICreateDevEnum, (void**)&pCreateDevEnum);
    if (hr != NOERROR)
	{
//		ErrMsg("Error Creating Device Enumerator");
		return;
	}
    CComPtr<IEnumMoniker> pEm;
    hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
								&pEm, 0);
    if (hr != NOERROR) 
	{
//		ErrMsg("Sorry, you have no video capture hardware");
		return;
    }
    pEm->Reset();
    ULONG cFetched;
    IMoniker *pM;
    while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
    {
		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) 
			{
				char str[2048];
				
				if (ptr->deviceId != -1)
				{
					ptr->next = new DeviceInfo();
					ptr = ptr->next;
				}
				ptr->deviceId = id++;
				WideCharToMultiByte(CP_ACP,0,var.bstrVal, -1, str, 2048, NULL, NULL);
				
				ptr->friendlyName = str;
				SysFreeString(var.bstrVal);
			}
			pBag->Release();
		}
		pM->Release();
    }
}
void ARFrameGrabber::ReportError(char *msg)
{
	MessageBox(NULL, msg, "ARFrameGrabber Error", MB_ICONSTOP);
}
// delete a media type, copied from the dshow base classes
void WINAPI DeleteMediaType(AM_MEDIA_TYPE *pmt)
{
    // allow NULL pointers for coding simplicity
    if (pmt == NULL) {
        return;
    }
    if (pmt->cbFormat != 0) {
        CoTaskMemFree((PVOID)pmt->pbFormat);
        // Strictly unnecessary but tidier
        pmt->cbFormat = 0;
        pmt->pbFormat = NULL;
    }
    if (pmt->pUnk != NULL) {
        pmt->pUnk->Release();
        pmt->pUnk = NULL;
    }
    CoTaskMemFree((PVOID)pmt);
}
--------------030709010201000802050902--
				 | 
			|||
| From: | Gerhard Reitmayr <reitmayr@i ...............> | Received: | Jan 18, 2002 | 
| To | artoolkit <artoolkit@h ..................> | ||
| Subject: | Some more mods to ARFrameGrabber :) | ||
This is a multi-part message in MIME format.
--------------000700090700010304040409
Content-Type: 
Content-Transfer-Encoding: 8bit
Hi,
I added the ability to define a video image size during initialization. 
It simlpy sets the first media type it finds that fits the desired 
format. If none is found, it doesn't change the default format. In any 
case there are to member functions that let you query the size of the 
video image.
maybe somebody finds this useful. please use the changes as you like.
bye,
   Gerhard
-- 
Gerhard Reitmayr  mailto:reitmayr@i ...............
                   tel:++ 43 1 58801 18856
Interactive Media Systems Group
Vienna University of Technology
--------------000700090700010304040409
Content-Type: text/plain; charset=windows-1252;
 name="ARFrameG.h"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ARFrameG.h"
// ARFrameGrabber.h: interface for the ARFrameGrabber class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_ARFRAMEGRABBER_H__C5553937_4BAB_4FEF_B4A6_1693AB0C99E3__INCLUDED_)
#define AFX_ARFRAMEGRABBER_H__C5553937_4BAB_4FEF_B4A6_1693AB0C99E3__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <dshow.h>
//#include <streams.h>
#include <atlbase.h>
#include <qedit.h>
class SmartString
{
public:
	SmartString():str(NULL) {}
	SmartString(char* pStr):str(NULL)
	{
		if (pStr)
		{
			int size = strlen(pStr);
			str = new char[size+1];
			strcpy(str, pStr);
		}
	}
	SmartString(SmartString& sStr)
	{
		SetString(sStr.GetBuffer());
	}
	~SmartString()
	{
		if (str)
			delete[] str;
	}
	SmartString& operator =(char* pStr)
	{
		SetString(pStr);
		return *this;
	}
	SmartString& operator =(SmartString& sStr)
	{
		SetString(sStr.GetBuffer());
		return *this;
	}
	char* GetBuffer() {return str;}
protected:
	void SetString(char *pStr)
	{
		if (str)
			delete[] str;
		if (!pStr)
		{
			str = NULL;
		}
		else
		{
			int size = strlen(pStr);
			str = new char[size + 1];
			strcpy(str, pStr);
		}
	}
	char* str;
};
struct DeviceInfo
{
	DeviceInfo():next(NULL), deviceId(-1)
	{
	} 
	~DeviceInfo()
	{
		if (next)
			delete next;
	}
	SmartString friendlyName;
	int			deviceId;	
	DeviceInfo* next;
};
class ARFrameGrabber  
{
public:
	ARFrameGrabber();
	virtual ~ARFrameGrabber();
	void Init(int deviceId, int = 0, int = 0);
	void BindFilter(int deviceId, IBaseFilter **pFilter);
	void GrabFrame(long* size, long** pBuffer);
	void GrabFrame();
	void Grab32BitFrame();
	long  GetBufferSize() {return bufferSize;}
	long* GetBuffer() {return pBuffer;}
	
	void SetFlippedImageHorizontal(bool flag) {flipImageH = flag;}
    void SetFlippedImageVertical(bool flag) {flipImageV = flag;}
    void SetFlippedImage(bool flag) {flipImageV =flag; flipImageH = flag;}
	void DisplayProperties();
	void EnumDevices(DeviceInfo *head);
    int  GetWidth() { return width; }
    int  GetHeight() { return height; }
protected:
	CComPtr<IGraphBuilder> pGraph;
	CComPtr<IBaseFilter> pDeviceFilter;
	CComPtr<IMediaControl> pMediaControl;
	CComPtr<IBaseFilter> pSampleGrabberFilter;
	CComPtr<ISampleGrabber> pSampleGrabber;
	CComPtr<IPin> pGrabberInput;
	CComPtr<IPin> pGrabberOutput;
	CComPtr<IPin> pCameraOutput;
	CComPtr<IMediaEvent> pMediaEvent;
	CComPtr<IBaseFilter> pNullFilter;
	CComPtr<IPin> pNullInputPin;    
	void FlipImage(long* pBuf);
private:
	void ReportError(char *msg);
    int  width;
    int  height;
	bool flipImageH;
    bool flipImageV;
	long bufferSize;
	long *pBuffer;
};
#endif // !defined(AFX_ARFRAMEGRABBER_H__C5553937_4BAB_4FEF_B4A6_1693AB0C99E3__INCLUDED_)
--------------000700090700010304040409
Content-Type: text/plain; charset=windows-1252;
 name="ARFrameG.cpp"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ARFrameG.cpp"
// ARFrameGrabber.cpp: implementation of the ARFrameGrabber class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ARFrameGrabber.h"
void WINAPI DeleteMediaType(AM_MEDIA_TYPE *pmt);
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
ARFrameGrabber::ARFrameGrabber():pBuffer(NULL), bufferSize(0), flipImageV(false), flipImageH(false)
{
}
ARFrameGrabber::~ARFrameGrabber()
{
	pMediaControl->Stop();
}
void ARFrameGrabber::Init(int deviceId, int width_, int height_)
{
	HRESULT hr = S_OK;
	// 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;
	mt.subtype = MEDIASUBTYPE_RGB32;
	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
	BindFilter(deviceId, &pDeviceFilter);
	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);
	// Set the grabbing size
    // First we iterate through the available media types and 
    // store the first one that fits the requested size.
    // If we have found one, we set it.
    // In any case we query the size of the current media type
    // to have this information for clients of this class.
    //     Gerhard Reitmayr <reitmayr@i ...............>
    CComPtr<IAMStreamConfig> pConfig;
    IEnumMediaTypes *pMedia;
    AM_MEDIA_TYPE *pmt = NULL, *pfnt = NULL;
    hr = pCameraOutput->EnumMediaTypes( &pMedia );
    if(SUCCEEDED(hr))
    {
        while(pMedia->Next(1, &pmt, 0) == S_OK)
        {
            if( pmt->formattype == FORMAT_VideoInfo )
            {
                VIDEOINFOHEADER *vih = (VIDEOINFOHEADER *)pmt->pbFormat;
                // printf("Size %i  %i\n", vih->bmiHeader.biWidth, vih->bmiHeader.biHeight );
                if( vih->bmiHeader.biWidth == width_ && vih->bmiHeader.biHeight == height_ )
                {
                    pfnt = pmt;
                    // printf("found mediatype with %i %i\n", vih->bmiHeader.biWidth, vih->bmiHeader.biHeight );
                    break;
                }
                DeleteMediaType( pmt );
                //delete pmt;
            }                        
        }
        pMedia->Release();
    }
    hr = pCameraOutput->QueryInterface( IID_IAMStreamConfig, (void **) &pConfig );
    if(SUCCEEDED(hr))
    {
        if( pfnt != NULL )
        {
            pConfig->SetFormat( pfnt );
            DeleteMediaType( pfnt );
            //delete pfnt;
        }
        hr = pConfig->GetFormat( &pfnt );
        if(SUCCEEDED(hr))
        {
            width = ((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biWidth;
            height = ((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biHeight;
        }
    }
    
	hr = pGraph->Connect(pCameraOutput, pGrabberInput);
	hr = pGraph->Connect(pGrabberOutput, pNullInputPin);
//	hr = pGraph->Render(pGrabberOutput);
	if (FAILED(hr))
	{
		switch(hr)
		{
		case VFW_S_NOPREVIEWPIN :
			break;
		case E_FAIL :
			break;
		case E_INVALIDARG :
			break;
		case E_POINTER :
			break;
		}
	}
	pSampleGrabber->SetBufferSamples(TRUE);
	pSampleGrabber->SetOneShot(TRUE);
}
void ARFrameGrabber::GrabFrame(long* size, long** pBuffer)
{
	if (!size)
		return;
	// don't want to leak mem, pBuffer must be NULL
	if (!pBuffer || *pBuffer)
		return;
	long evCode;
	pMediaControl->Run();
	pMediaEvent->WaitForCompletion(INFINITE, &evCode);
	pSampleGrabber->GetCurrentBuffer(size, NULL);
	if (*size)
	{
		*pBuffer = new long[*size];
	}
	pSampleGrabber->GetCurrentBuffer(size, *pBuffer);
}
void ARFrameGrabber::GrabFrame()
{
	long evCode;
	long size = 0;
	pMediaControl->Run();
	pMediaEvent->WaitForCompletion(INFINITE, &evCode);
	pSampleGrabber->GetCurrentBuffer(&size, NULL);
	// 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];
	}
	pSampleGrabber->GetCurrentBuffer(&size, pBuffer);
	if (flipImageV | flipImageH)
		FlipImage(pBuffer);
}
void ARFrameGrabber::FlipImage(long* pBuf)
{
	DWORD *ptr = (DWORD*)pBuf;
	int pixelCount = bufferSize/4;
 
	if (!pBuf)
		return;
    // Added code for more image manipulations
    // Gerhard Reitmayr <reitmayr@i ...............
    if( flipImageV )
    {
        if( flipImageH )
        {
            // both flips set -> rotation about 180 degree
	        for (int index = 0; index < pixelCount/2; index++)
	        {
		        ptr[index] = ptr[index] ^ ptr[pixelCount - index - 1];
		        ptr[pixelCount - index - 1] = ptr[index] ^ ptr[pixelCount - index - 1];
		        ptr[index] = ptr[index] ^ ptr[pixelCount - index - 1];
	        }
        } 
        else  
        {
            // only vertical flip 
            for( int line = 0; line < height/2; line++ )
                for( int pixel = 0; pixel < width; pixel ++ )
                {
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[pixelCount - line*width - (width - pixel )];
                    ptr[pixelCount - line*width - (width - pixel )] = ptr[line*width+pixel] ^ ptr[pixelCount - line*width - (width - pixel )];
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[pixelCount - line*width - (width - pixel )];
                }
        }
    }
    else 
    {
        if( flipImageH )
        {
            // only horizontal flip
            for( int line = 0; line < height; line++ )
                for( int pixel = 0; pixel < width/2; pixel ++ )
                {
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[line*width + (width - pixel )];
                    ptr[line*width + (width - pixel )] = ptr[line*width+pixel] ^ ptr[line*width + (width - pixel )];
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[line*width + (width - pixel )];
                }
        }
    }
}
void ARFrameGrabber::Grab32BitFrame()
{
	long evCode;
	long size = 0;
	long* pData;
	unsigned char* pTemp;
	unsigned char* ptr;
	pMediaControl->Run();
	pMediaEvent->WaitForCompletion(INFINITE, &evCode);
	pSampleGrabber->GetCurrentBuffer(&size, NULL);
	if (size != bufferSize)
	{
		if (pBuffer)
			delete[] pBuffer;
		bufferSize = size/3*4;  // add space for padding
		pBuffer = new long[bufferSize];
	}
	pData= (long*) new unsigned char[size];
	pSampleGrabber->GetCurrentBuffer(&size, pData);
	ptr = ((unsigned char*)pBuffer) + bufferSize - 1;
	pTemp = (unsigned char*) pData;
	// do the padding
	for (int index = 0; index < size/3; index++)
	{
		unsigned char r = *(pTemp++);
		unsigned char g = *(pTemp++);
		unsigned char b = *(pTemp++);
		*(ptr--) = 0;
		*(ptr--) = b;
		*(ptr--) = g;
		*(ptr--) = r;
	}
/*
	for (int index = 0; index < size; index++)
	{
		*ptr = ((unsigned char *)pTemp)[index];
		ptr--;
		if (index % 3 == 2)
		{
			*ptr = 0;
			ptr--;
		}
	}
*/
	delete[] pData;
}
void ARFrameGrabber::BindFilter(int deviceId, IBaseFilter **pFilter)
{
	if (deviceId < 0)
		return;
	
    // enumerate all video capture devices
	CComPtr<ICreateDevEnum> pCreateDevEnum;
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
			  IID_ICreateDevEnum, (void**)&pCreateDevEnum);
    if (hr != NOERROR)
	{
//		ErrMsg("Error Creating Device Enumerator");
		return;
	}
    CComPtr<IEnumMoniker> pEm;
    hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
								&pEm, 0);
    if (hr != NOERROR) 
	{
//		ErrMsg("Sorry, you have no video capture hardware");
		return;
    }
    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++;
    }
}
void ARFrameGrabber::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.p),
			caGUID.cElems,
			caGUID.pElems,
			0,
			0,
			NULL);
		CoTaskMemFree(caGUID.pElems);
		PinInfo.pFilter->Release();
	}
}
void ARFrameGrabber::EnumDevices(DeviceInfo *head)
{
	if (!head)
		return;
	DeviceInfo *ptr = head;
	int id = 0;
	
    // enumerate all video capture devices
	CComPtr<ICreateDevEnum> pCreateDevEnum;
//    ICreateDevEnum *pCreateDevEnum;
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
			  IID_ICreateDevEnum, (void**)&pCreateDevEnum);
    if (hr != NOERROR)
	{
//		ErrMsg("Error Creating Device Enumerator");
		return;
	}
    CComPtr<IEnumMoniker> pEm;
    hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
								&pEm, 0);
    if (hr != NOERROR) 
	{
//		ErrMsg("Sorry, you have no video capture hardware");
		return;
    }
    pEm->Reset();
    ULONG cFetched;
    IMoniker *pM;
    while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
    {
		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) 
			{
				char str[2048];
				
				if (ptr->deviceId != -1)
				{
					ptr->next = new DeviceInfo();
					ptr = ptr->next;
				}
				ptr->deviceId = id++;
				WideCharToMultiByte(CP_ACP,0,var.bstrVal, -1, str, 2048, NULL, NULL);
				
				ptr->friendlyName = str;
				SysFreeString(var.bstrVal);
			}
			pBag->Release();
		}
		pM->Release();
    }
}
void ARFrameGrabber::ReportError(char *msg)
{
	MessageBox(NULL, msg, "ARFrameGrabber Error", MB_ICONSTOP);
}
// delete a media type, copied from the dshow base classes
void WINAPI DeleteMediaType(AM_MEDIA_TYPE *pmt)
{
    // allow NULL pointers for coding simplicity
    if (pmt == NULL) {
        return;
    }
    if (pmt->cbFormat != 0) {
        CoTaskMemFree((PVOID)pmt->pbFormat);
        // Strictly unnecessary but tidier
        pmt->cbFormat = 0;
        pmt->pbFormat = NULL;
    }
    if (pmt->pUnk != NULL) {
        pmt->pUnk->Release();
        pmt->pUnk = NULL;
    }
    CoTaskMemFree((PVOID)pmt);
}
--------------000700090700010304040409--
				 | 
			|||
| From: | Gerhard Reitmayr <reitmayr@i ...............> | Received: | Jan 23, 2002 | 
| To | artoolkit <artoolkit@h ..................> | ||
| Subject: | Re: Some more mods to ARFrameGrabber :) | ||
This is a multi-part message in MIME format.
--------------030002000900000205080807
Content-Type: 
Content-Transfer-Encoding: 8bit
Hi,
there was a bug in the last version of ARFrameGrabber I sent out. Using 
the wrong pointer variable in one place could yield a null pointer 
access :(. This file fixes it.
bye,
   Gerhard
Gerhard Reitmayr wrote:
> Hi,
> 
> I added the ability to define a video image size during initialization. 
> It simlpy sets the first media type it finds that fits the desired 
> format. If none is found, it doesn't change the default format. In any 
> case there are to member functions that let you query the size of the 
> video image.
> 
> maybe somebody finds this useful. please use the changes as you like.
> 
> bye,
>   Gerhard
> 
> 
-- 
Gerhard Reitmayr  mailto:reitmayr@i ...............
                   tel:++ 43 1 58801 18856
Interactive Media Systems Group
Vienna University of Technology
--------------030002000900000205080807
Content-Type: text/plain; charset=windows-1252;
 name="ARFrameG.cpp"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ARFrameG.cpp"
// ARFrameGrabber.cpp: implementation of the ARFrameGrabber class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ARFrameGrabber.h"
void WINAPI DeleteMediaType(AM_MEDIA_TYPE *pmt);
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
ARFrameGrabber::ARFrameGrabber():pBuffer(NULL), bufferSize(0), flipImageV(false), flipImageH(false)
{
}
ARFrameGrabber::~ARFrameGrabber()
{
	pMediaControl->Stop();
}
void ARFrameGrabber::Init(int deviceId, int width_, int height_)
{
	HRESULT hr = S_OK;
	// 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;
	mt.subtype = MEDIASUBTYPE_RGB32;
	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
	BindFilter(deviceId, &pDeviceFilter);
	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);
	// Set the grabbing size
    // First we iterate through the available media types and 
    // store the first one that fits the requested size.
    // If we have found one, we set it.
    // In any case we query the size of the current media type
    // to have this information for clients of this class.
    //     Gerhard Reitmayr <reitmayr@i ...............>
    CComPtr<IAMStreamConfig> pConfig;
    IEnumMediaTypes *pMedia;
    AM_MEDIA_TYPE *pmt = NULL, *pfnt = NULL;
    hr = pCameraOutput->EnumMediaTypes( &pMedia );
    if(SUCCEEDED(hr))
    {
        while(pMedia->Next(1, &pmt, 0) == S_OK)
        {
            if( pmt->formattype == FORMAT_VideoInfo )
            {
                VIDEOINFOHEADER *vih = (VIDEOINFOHEADER *)pmt->pbFormat;
                // printf("Size %i  %i\n", vih->bmiHeader.biWidth, vih->bmiHeader.biHeight );
                if( vih->bmiHeader.biWidth == width_ && vih->bmiHeader.biHeight == height_ )
                {
                    pfnt = pmt;
                    // printf("found mediatype with %i %i\n", vih->bmiHeader.biWidth, vih->bmiHeader.biHeight );
                    break;
                }
                DeleteMediaType( pmt );
            }                        
        }
        pMedia->Release();
    }
    hr = pCameraOutput->QueryInterface( IID_IAMStreamConfig, (void **) &pConfig );
    if(SUCCEEDED(hr))
    {
        if( pfnt != NULL )
        {
            pConfig->SetFormat( pfnt );
            DeleteMediaType( pfnt );
        }
        hr = pConfig->GetFormat( &pfnt );
        if(SUCCEEDED(hr))
        {
            width = ((VIDEOINFOHEADER *)pfnt->pbFormat)->bmiHeader.biWidth;
            height = ((VIDEOINFOHEADER *)pfnt->pbFormat)->bmiHeader.biHeight;
            DeleteMediaType( pfnt );
        }
    }
    
	hr = pGraph->Connect(pCameraOutput, pGrabberInput);
	hr = pGraph->Connect(pGrabberOutput, pNullInputPin);
//	hr = pGraph->Render(pGrabberOutput);
	if (FAILED(hr))
	{
		switch(hr)
		{
		case VFW_S_NOPREVIEWPIN :
			break;
		case E_FAIL :
			break;
		case E_INVALIDARG :
			break;
		case E_POINTER :
			break;
		}
	}
	pSampleGrabber->SetBufferSamples(TRUE);
	pSampleGrabber->SetOneShot(TRUE);
}
void ARFrameGrabber::GrabFrame(long* size, long** pBuffer)
{
	if (!size)
		return;
	// don't want to leak mem, pBuffer must be NULL
	if (!pBuffer || *pBuffer)
		return;
	long evCode;
	pMediaControl->Run();
	pMediaEvent->WaitForCompletion(INFINITE, &evCode);
	pSampleGrabber->GetCurrentBuffer(size, NULL);
	if (*size)
	{
		*pBuffer = new long[*size];
	}
	pSampleGrabber->GetCurrentBuffer(size, *pBuffer);
}
void ARFrameGrabber::GrabFrame()
{
	long evCode;
	long size = 0;
	pMediaControl->Run();
	pMediaEvent->WaitForCompletion(INFINITE, &evCode);
	pSampleGrabber->GetCurrentBuffer(&size, NULL);
	// 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];
	}
	pSampleGrabber->GetCurrentBuffer(&size, pBuffer);
	if (flipImageV | flipImageH)
		FlipImage(pBuffer);
}
void ARFrameGrabber::FlipImage(long* pBuf)
{
	DWORD *ptr = (DWORD*)pBuf;
	int pixelCount = bufferSize/4;
 
	if (!pBuf)
		return;
    // Added code for more image manipulations
    // Gerhard Reitmayr <reitmayr@i ...............
    if( flipImageV )
    {
        if( flipImageH )
        {
            // both flips set -> rotation about 180 degree
	        for (int index = 0; index < pixelCount/2; index++)
	        {
		        ptr[index] = ptr[index] ^ ptr[pixelCount - index - 1];
		        ptr[pixelCount - index - 1] = ptr[index] ^ ptr[pixelCount - index - 1];
		        ptr[index] = ptr[index] ^ ptr[pixelCount - index - 1];
	        }
        } 
        else  
        {
            // only vertical flip 
            for( int line = 0; line < height/2; line++ )
                for( int pixel = 0; pixel < width; pixel ++ )
                {
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[pixelCount - line*width - (width - pixel )];
                    ptr[pixelCount - line*width - (width - pixel )] = ptr[line*width+pixel] ^ ptr[pixelCount - line*width - (width - pixel )];
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[pixelCount - line*width - (width - pixel )];
                }
        }
    }
    else 
    {
        if( flipImageH )
        {
            // only horizontal flip
            for( int line = 0; line < height; line++ )
                for( int pixel = 0; pixel < width/2; pixel ++ )
                {
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[line*width + (width - pixel )];
                    ptr[line*width + (width - pixel )] = ptr[line*width+pixel] ^ ptr[line*width + (width - pixel )];
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[line*width + (width - pixel )];
                }
        }
    }
}
void ARFrameGrabber::Grab32BitFrame()
{
	long evCode;
	long size = 0;
	long* pData;
	unsigned char* pTemp;
	unsigned char* ptr;
	pMediaControl->Run();
	pMediaEvent->WaitForCompletion(INFINITE, &evCode);
	pSampleGrabber->GetCurrentBuffer(&size, NULL);
	if (size != bufferSize)
	{
		if (pBuffer)
			delete[] pBuffer;
		bufferSize = size/3*4;  // add space for padding
		pBuffer = new long[bufferSize];
	}
	pData= (long*) new unsigned char[size];
	pSampleGrabber->GetCurrentBuffer(&size, pData);
	ptr = ((unsigned char*)pBuffer) + bufferSize - 1;
	pTemp = (unsigned char*) pData;
	// do the padding
	for (int index = 0; index < size/3; index++)
	{
		unsigned char r = *(pTemp++);
		unsigned char g = *(pTemp++);
		unsigned char b = *(pTemp++);
		*(ptr--) = 0;
		*(ptr--) = b;
		*(ptr--) = g;
		*(ptr--) = r;
	}
/*
	for (int index = 0; index < size; index++)
	{
		*ptr = ((unsigned char *)pTemp)[index];
		ptr--;
		if (index % 3 == 2)
		{
			*ptr = 0;
			ptr--;
		}
	}
*/
	delete[] pData;
}
void ARFrameGrabber::BindFilter(int deviceId, IBaseFilter **pFilter)
{
	if (deviceId < 0)
		return;
	
    // enumerate all video capture devices
	CComPtr<ICreateDevEnum> pCreateDevEnum;
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
			  IID_ICreateDevEnum, (void**)&pCreateDevEnum);
    if (hr != NOERROR)
	{
//		ErrMsg("Error Creating Device Enumerator");
		return;
	}
    CComPtr<IEnumMoniker> pEm;
    hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
								&pEm, 0);
    if (hr != NOERROR) 
	{
//		ErrMsg("Sorry, you have no video capture hardware");
		return;
    }
    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++;
    }
}
void ARFrameGrabber::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.p),
			caGUID.cElems,
			caGUID.pElems,
			0,
			0,
			NULL);
		CoTaskMemFree(caGUID.pElems);
		PinInfo.pFilter->Release();
	}
}
void ARFrameGrabber::EnumDevices(DeviceInfo *head)
{
	if (!head)
		return;
	DeviceInfo *ptr = head;
	int id = 0;
	
    // enumerate all video capture devices
	CComPtr<ICreateDevEnum> pCreateDevEnum;
//    ICreateDevEnum *pCreateDevEnum;
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
			  IID_ICreateDevEnum, (void**)&pCreateDevEnum);
    if (hr != NOERROR)
	{
//		ErrMsg("Error Creating Device Enumerator");
		return;
	}
    CComPtr<IEnumMoniker> pEm;
    hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
								&pEm, 0);
    if (hr != NOERROR) 
	{
//		ErrMsg("Sorry, you have no video capture hardware");
		return;
    }
    pEm->Reset();
    ULONG cFetched;
    IMoniker *pM;
    while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
    {
		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) 
			{
				char str[2048];
				
				if (ptr->deviceId != -1)
				{
					ptr->next = new DeviceInfo();
					ptr = ptr->next;
				}
				ptr->deviceId = id++;
				WideCharToMultiByte(CP_ACP,0,var.bstrVal, -1, str, 2048, NULL, NULL);
				
				ptr->friendlyName = str;
				SysFreeString(var.bstrVal);
			}
			pBag->Release();
		}
		pM->Release();
    }
}
void ARFrameGrabber::ReportError(char *msg)
{
	MessageBox(NULL, msg, "ARFrameGrabber Error", MB_ICONSTOP);
}
// delete a media type, copied from the dshow base classes
void WINAPI DeleteMediaType(AM_MEDIA_TYPE *pmt)
{
    // allow NULL pointers for coding simplicity
    if (pmt == NULL) {
        return;
    }
    if (pmt->cbFormat != 0) {
        CoTaskMemFree((PVOID)pmt->pbFormat);
        // Strictly unnecessary but tidier
        pmt->cbFormat = 0;
        pmt->pbFormat = NULL;
    }
    if (pmt->pUnk != NULL) {
        pmt->pUnk->Release();
        pmt->pUnk = NULL;
    }
    CoTaskMemFree((PVOID)pmt);
}
--------------030002000900000205080807--
				 | 
			|||
| From: | Gerhard Reitmayr <reitmayr@i ...............> | Received: | Jan 23, 2002 | 
| To | artoolkit <artoolkit@h ..................> | ||
| Subject: | Re: Some more mods to ARFrameGrabber :) | ||
This is a multi-part message in MIME format.
--------------050106070301000300080408
Content-Type: 
Content-Transfer-Encoding: 8bit
Hi,
there was a bug in the last version of ARFrameGrabber I sent out. Using 
the wrong pointer variable in one place could yield a null pointer 
access :(. This file fixes it.
bye,
   Gerhard
Gerhard Reitmayr wrote:
> Hi,
> 
> I added the ability to define a video image size during initialization. 
> It simlpy sets the first media type it finds that fits the desired 
> format. If none is found, it doesn't change the default format. In any 
> case there are to member functions that let you query the size of the 
> video image.
> 
> maybe somebody finds this useful. please use the changes as you like.
> 
> bye,
>   Gerhard
> 
> 
-- 
Gerhard Reitmayr  mailto:reitmayr@i ...............
                   tel:++ 43 1 58801 18856
Interactive Media Systems Group
Vienna University of Technology
--------------050106070301000300080408
Content-Type: text/plain; charset=windows-1252;
 name="ARFrameG.cpp"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ARFrameG.cpp"
// ARFrameGrabber.cpp: implementation of the ARFrameGrabber class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ARFrameGrabber.h"
void WINAPI DeleteMediaType(AM_MEDIA_TYPE *pmt);
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
ARFrameGrabber::ARFrameGrabber():pBuffer(NULL), bufferSize(0), flipImageV(false), flipImageH(false)
{
}
ARFrameGrabber::~ARFrameGrabber()
{
	pMediaControl->Stop();
}
void ARFrameGrabber::Init(int deviceId, int width_, int height_)
{
	HRESULT hr = S_OK;
	// 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;
	mt.subtype = MEDIASUBTYPE_RGB32;
	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
	BindFilter(deviceId, &pDeviceFilter);
	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);
	// Set the grabbing size
    // First we iterate through the available media types and 
    // store the first one that fits the requested size.
    // If we have found one, we set it.
    // In any case we query the size of the current media type
    // to have this information for clients of this class.
    //     Gerhard Reitmayr <reitmayr@i ...............>
    CComPtr<IAMStreamConfig> pConfig;
    IEnumMediaTypes *pMedia;
    AM_MEDIA_TYPE *pmt = NULL, *pfnt = NULL;
    hr = pCameraOutput->EnumMediaTypes( &pMedia );
    if(SUCCEEDED(hr))
    {
        while(pMedia->Next(1, &pmt, 0) == S_OK)
        {
            if( pmt->formattype == FORMAT_VideoInfo )
            {
                VIDEOINFOHEADER *vih = (VIDEOINFOHEADER *)pmt->pbFormat;
                // printf("Size %i  %i\n", vih->bmiHeader.biWidth, vih->bmiHeader.biHeight );
                if( vih->bmiHeader.biWidth == width_ && vih->bmiHeader.biHeight == height_ )
                {
                    pfnt = pmt;
                    // printf("found mediatype with %i %i\n", vih->bmiHeader.biWidth, vih->bmiHeader.biHeight );
                    break;
                }
                DeleteMediaType( pmt );
            }                        
        }
        pMedia->Release();
    }
    hr = pCameraOutput->QueryInterface( IID_IAMStreamConfig, (void **) &pConfig );
    if(SUCCEEDED(hr))
    {
        if( pfnt != NULL )
        {
            pConfig->SetFormat( pfnt );
            DeleteMediaType( pfnt );
        }
        hr = pConfig->GetFormat( &pfnt );
        if(SUCCEEDED(hr))
        {
            width = ((VIDEOINFOHEADER *)pfnt->pbFormat)->bmiHeader.biWidth;
            height = ((VIDEOINFOHEADER *)pfnt->pbFormat)->bmiHeader.biHeight;
            DeleteMediaType( pfnt );
        }
    }
    
	hr = pGraph->Connect(pCameraOutput, pGrabberInput);
	hr = pGraph->Connect(pGrabberOutput, pNullInputPin);
//	hr = pGraph->Render(pGrabberOutput);
	if (FAILED(hr))
	{
		switch(hr)
		{
		case VFW_S_NOPREVIEWPIN :
			break;
		case E_FAIL :
			break;
		case E_INVALIDARG :
			break;
		case E_POINTER :
			break;
		}
	}
	pSampleGrabber->SetBufferSamples(TRUE);
	pSampleGrabber->SetOneShot(TRUE);
}
void ARFrameGrabber::GrabFrame(long* size, long** pBuffer)
{
	if (!size)
		return;
	// don't want to leak mem, pBuffer must be NULL
	if (!pBuffer || *pBuffer)
		return;
	long evCode;
	pMediaControl->Run();
	pMediaEvent->WaitForCompletion(INFINITE, &evCode);
	pSampleGrabber->GetCurrentBuffer(size, NULL);
	if (*size)
	{
		*pBuffer = new long[*size];
	}
	pSampleGrabber->GetCurrentBuffer(size, *pBuffer);
}
void ARFrameGrabber::GrabFrame()
{
	long evCode;
	long size = 0;
	pMediaControl->Run();
	pMediaEvent->WaitForCompletion(INFINITE, &evCode);
	pSampleGrabber->GetCurrentBuffer(&size, NULL);
	// 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];
	}
	pSampleGrabber->GetCurrentBuffer(&size, pBuffer);
	if (flipImageV | flipImageH)
		FlipImage(pBuffer);
}
void ARFrameGrabber::FlipImage(long* pBuf)
{
	DWORD *ptr = (DWORD*)pBuf;
	int pixelCount = bufferSize/4;
 
	if (!pBuf)
		return;
    // Added code for more image manipulations
    // Gerhard Reitmayr <reitmayr@i ...............
    if( flipImageV )
    {
        if( flipImageH )
        {
            // both flips set -> rotation about 180 degree
	        for (int index = 0; index < pixelCount/2; index++)
	        {
		        ptr[index] = ptr[index] ^ ptr[pixelCount - index - 1];
		        ptr[pixelCount - index - 1] = ptr[index] ^ ptr[pixelCount - index - 1];
		        ptr[index] = ptr[index] ^ ptr[pixelCount - index - 1];
	        }
        } 
        else  
        {
            // only vertical flip 
            for( int line = 0; line < height/2; line++ )
                for( int pixel = 0; pixel < width; pixel ++ )
                {
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[pixelCount - line*width - (width - pixel )];
                    ptr[pixelCount - line*width - (width - pixel )] = ptr[line*width+pixel] ^ ptr[pixelCount - line*width - (width - pixel )];
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[pixelCount - line*width - (width - pixel )];
                }
        }
    }
    else 
    {
        if( flipImageH )
        {
            // only horizontal flip
            for( int line = 0; line < height; line++ )
                for( int pixel = 0; pixel < width/2; pixel ++ )
                {
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[line*width + (width - pixel )];
                    ptr[line*width + (width - pixel )] = ptr[line*width+pixel] ^ ptr[line*width + (width - pixel )];
                    ptr[line*width+pixel] = ptr[line*width+pixel] ^ ptr[line*width + (width - pixel )];
                }
        }
    }
}
void ARFrameGrabber::Grab32BitFrame()
{
	long evCode;
	long size = 0;
	long* pData;
	unsigned char* pTemp;
	unsigned char* ptr;
	pMediaControl->Run();
	pMediaEvent->WaitForCompletion(INFINITE, &evCode);
	pSampleGrabber->GetCurrentBuffer(&size, NULL);
	if (size != bufferSize)
	{
		if (pBuffer)
			delete[] pBuffer;
		bufferSize = size/3*4;  // add space for padding
		pBuffer = new long[bufferSize];
	}
	pData= (long*) new unsigned char[size];
	pSampleGrabber->GetCurrentBuffer(&size, pData);
	ptr = ((unsigned char*)pBuffer) + bufferSize - 1;
	pTemp = (unsigned char*) pData;
	// do the padding
	for (int index = 0; index < size/3; index++)
	{
		unsigned char r = *(pTemp++);
		unsigned char g = *(pTemp++);
		unsigned char b = *(pTemp++);
		*(ptr--) = 0;
		*(ptr--) = b;
		*(ptr--) = g;
		*(ptr--) = r;
	}
/*
	for (int index = 0; index < size; index++)
	{
		*ptr = ((unsigned char *)pTemp)[index];
		ptr--;
		if (index % 3 == 2)
		{
			*ptr = 0;
			ptr--;
		}
	}
*/
	delete[] pData;
}
void ARFrameGrabber::BindFilter(int deviceId, IBaseFilter **pFilter)
{
	if (deviceId < 0)
		return;
	
    // enumerate all video capture devices
	CComPtr<ICreateDevEnum> pCreateDevEnum;
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
			  IID_ICreateDevEnum, (void**)&pCreateDevEnum);
    if (hr != NOERROR)
	{
//		ErrMsg("Error Creating Device Enumerator");
		return;
	}
    CComPtr<IEnumMoniker> pEm;
    hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
								&pEm, 0);
    if (hr != NOERROR) 
	{
//		ErrMsg("Sorry, you have no video capture hardware");
		return;
    }
    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++;
    }
}
void ARFrameGrabber::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.p),
			caGUID.cElems,
			caGUID.pElems,
			0,
			0,
			NULL);
		CoTaskMemFree(caGUID.pElems);
		PinInfo.pFilter->Release();
	}
}
void ARFrameGrabber::EnumDevices(DeviceInfo *head)
{
	if (!head)
		return;
	DeviceInfo *ptr = head;
	int id = 0;
	
    // enumerate all video capture devices
	CComPtr<ICreateDevEnum> pCreateDevEnum;
//    ICreateDevEnum *pCreateDevEnum;
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
			  IID_ICreateDevEnum, (void**)&pCreateDevEnum);
    if (hr != NOERROR)
	{
//		ErrMsg("Error Creating Device Enumerator");
		return;
	}
    CComPtr<IEnumMoniker> pEm;
    hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
								&pEm, 0);
    if (hr != NOERROR) 
	{
//		ErrMsg("Sorry, you have no video capture hardware");
		return;
    }
    pEm->Reset();
    ULONG cFetched;
    IMoniker *pM;
    while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
    {
		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) 
			{
				char str[2048];
				
				if (ptr->deviceId != -1)
				{
					ptr->next = new DeviceInfo();
					ptr = ptr->next;
				}
				ptr->deviceId = id++;
				WideCharToMultiByte(CP_ACP,0,var.bstrVal, -1, str, 2048, NULL, NULL);
				
				ptr->friendlyName = str;
				SysFreeString(var.bstrVal);
			}
			pBag->Release();
		}
		pM->Release();
    }
}
void ARFrameGrabber::ReportError(char *msg)
{
	MessageBox(NULL, msg, "ARFrameGrabber Error", MB_ICONSTOP);
}
// delete a media type, copied from the dshow base classes
void WINAPI DeleteMediaType(AM_MEDIA_TYPE *pmt)
{
    // allow NULL pointers for coding simplicity
    if (pmt == NULL) {
        return;
    }
    if (pmt->cbFormat != 0) {
        CoTaskMemFree((PVOID)pmt->pbFormat);
        // Strictly unnecessary but tidier
        pmt->cbFormat = 0;
        pmt->pbFormat = NULL;
    }
    if (pmt->pUnk != NULL) {
        pmt->pUnk->Release();
        pmt->pUnk = NULL;
    }
    CoTaskMemFree((PVOID)pmt);
}
--------------050106070301000300080408--
				 | 
			|||