JD2022-TU1/main/extern/Camcam/LIBS/Input/WEBCAM.cpp

1166 lines
27 KiB
C++

#define WIN32_LEAN_AND_MEAN
#include <atlbase.h>
#include <windows.h>
#include <dshow.h>
#include <ks.h>
#include <ksmedia.h>
#include <qedit.h>
#include "SCENE.h"
extern TCHAR CurrWebCam[256];
int GetWebCamByName(char *compressorsName, IBaseFilter **FilterPtr);
int CAMERA_SpecifyedW = 320;
#pragma optimize("",off)
#define MYDRV "YouUp"
#define NB_UNFRENDLY_CAMS 2
static char *unfrendlyCams[NB_UNFRENDLY_CAMS] = { MYDRV, "CamCam" };
//#define Draw_Histogram
#define CAM_ERROR 1
#define CAM_UNFRENDLY 2
#define CAM_IN_USE 3
#define CAM_USED 4
//#pragma optimize("",off)
struct DeviceInfo
{
DeviceInfo():next(NULL), deviceId(-1)
{
}
~DeviceInfo()
{
if (next)
delete next;
}
char friendlyName[2048];
int deviceId;
DeviceInfo* next;
};
class C2SampleGrabberCB : public ISampleGrabberCB
{
public:
u32 ImageCounter;
STDMETHODIMP_(ULONG) AddRef() { return 2; }
STDMETHODIMP_(ULONG) Release() { return 1; }
STDMETHODIMP QueryInterface(REFIID riid, void ** ppv)
{
if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown ) {
*ppv = (void *) static_cast<ISampleGrabberCB*> ( this );
return NOERROR;
}
return E_NOINTERFACE;
}
STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample ){ImageCounter ++;return 0;}
STDMETHODIMP BufferCB( double dblSampleTime, BYTE * pBuffer, long lBufferSize ){ImageCounter ++;return 0;}
};
class ARFrameGrabber
{
public:
HRESULT hrinit ;
VIDEOINFOHEADER Vih;
char str[2048];
long hardwareFlipAvailable;
long hardwareFlipSet;
C2SampleGrabberCB CB;
ARFrameGrabber();
virtual ~ARFrameGrabber();
int Init(int deviceId);
void BindFilter(int deviceId, IBaseFilter **pFilter);
int GrabFrame();
BOOL SetVideoControl(long mask, bool remove = 0);
long GetBufferSize() {return bufferSize;}
long* GetBuffer() {return pBuffer;}
void DisplayProperties();
protected:
CComPtr<IPin> pGrabberInput;
CComPtr<IPin> pGrabberOutput;
CComPtr<IPin> pCameraOutput;
CComPtr<IPin> pNullInputPin;
CComPtr<IGraphBuilder> pGraph;
CComPtr<IBaseFilter> pDeviceFilter;
CComPtr<IBaseFilter> pSampleGrabberFilter;
CComPtr<IBaseFilter> pNullFilter;
CComPtr<IMediaControl> pMediaControl;
CComPtr<ISampleGrabber> pSampleGrabber;
CComPtr<IMediaEvent> pMediaEvent;
private:
void ReportError(char *msg);
long bufferSize;
long *pBuffer;
};
ARFrameGrabber::ARFrameGrabber():pBuffer(NULL), bufferSize(0)
{
// memset(this,0,sizeof(*this));
}
ARFrameGrabber::~ARFrameGrabber()
{
if (pGrabberInput) pGrabberInput.Release();
if (pGrabberOutput) pGrabberOutput.Release();
if (pCameraOutput) pCameraOutput.Release();
if (pNullInputPin) pNullInputPin.Release();
if (pMediaControl) pMediaControl->Stop();
if (pMediaControl) pMediaControl.Release();
if (pMediaEvent) pMediaEvent.Release();
if (pSampleGrabber) pSampleGrabber.Release();
if (pSampleGrabberFilter) pSampleGrabberFilter.Release();
if (pNullFilter) pNullFilter.Release();
if (pDeviceFilter) pDeviceFilter.Release();
if (pGraph) pGraph.Release();
if (pBuffer) CC_free(pBuffer);
pBuffer = NULL;
bufferSize = 0;
}
void FAIL_TEST(HRESULT hr)
{
if (hr != S_OK)
hr = hr;
}
int ARFrameGrabber::Init(int deviceId)
{
HRESULT hr = S_OK;
hrinit = S_OK;
// Bind Device Filter. We know the device because the id was passed in
str[0] = 0;
BindFilter(deviceId, &pDeviceFilter);
char SaveStr9;
SaveStr9 = str[9];
str[9] = 0;
for (int uf=0; uf < NB_UNFRENDLY_CAMS; uf++)
{
if (strnicmp(unfrendlyCams[uf],str, strlen(unfrendlyCams[uf])) == 0)
{
hrinit = E_FAIL ;
return CAM_UNFRENDLY;
}
}
str[9] = SaveStr9;
if (!pDeviceFilter)
{
hrinit = E_FAIL ;
return CAM_ERROR;
}
// 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");
//hr = pGraph->AddSourceFilter(L"X:\\Bins\\je suis ton pere.avi", L"Source", &pDeviceFilter);
if (S_OK != pGraph->AddFilter(pDeviceFilter, NULL))
{
pDeviceFilter.Release();
pGraph.Release();
hrinit = E_FAIL ;
return CAM_ERROR;
}
/*
CComPtr<IAMVideoProcAmp> videoProp;
pDeviceFilter->QueryInterface(IID_IAMVideoProcAmp, (void **)&vidProp);
if (vidProp)
{
long Min, Max, SteppingDelta, Default, CapsFlag;
hr = vidProp->GetRange(VideoProcAmp_Brightness, &Min, &Max, &SteppingDelta, &Default, &CapsFlag);
hr = vidProp->GetRange(VideoProcAmp_Contrast, &Min, &Max, &SteppingDelta, &Default, &CapsFlag);
hr = vidProp->GetRange(VideoProcAmp_Hue, &Min, &Max, &SteppingDelta, &Default, &CapsFlag);
hr = vidProp->GetRange(VideoProcAmp_Saturation, &Min, &Max, &SteppingDelta, &Default, &CapsFlag);
hr = vidProp->GetRange(VideoProcAmp_Sharpness, &Min, &Max, &SteppingDelta, &Default, &CapsFlag);
hr = vidProp->GetRange(VideoProcAmp_Gamma, &Min, &Max, &SteppingDelta, &Default, &CapsFlag);
hr = vidProp->GetRange(VideoProcAmp_ColorEnable, &Min, &Max, &SteppingDelta, &Default, &CapsFlag);
hr = vidProp->GetRange(VideoProcAmp_WhiteBalance, &Min, &Max, &SteppingDelta, &Default, &CapsFlag);
hr = vidProp->GetRange(VideoProcAmp_BacklightCompensation, &Min, &Max, &SteppingDelta, &Default, &CapsFlag);
hr = vidProp->GetRange(VideoProcAmp_Gain, &Min, &Max, &SteppingDelta, &Default, &CapsFlag);
flags = 2;
vidProp->Get(VideoProcAmp_Gain, &value, &flags);
flags = 0;
}
*/
CComPtr<IEnumPins> pEnum;
if (S_OK != pDeviceFilter->EnumPins(&pEnum))
{
pDeviceFilter.Release();
pGraph.Release();
hrinit = E_FAIL ;
return CAM_ERROR;
}
if (S_OK != pEnum->Reset())
{
pDeviceFilter.Release();
pGraph.Release();
pEnum.Release();
hrinit = E_FAIL ;
return CAM_ERROR;
}
if (S_OK != pEnum->Next(1, &pCameraOutput, NULL))
{
pDeviceFilter.Release();
pGraph.Release();
hrinit = E_FAIL ;
return CAM_ERROR;
}
// get flip available
hardwareFlipAvailable = 0;
hardwareFlipSet = 0;
pEnum.Release();
pSampleGrabberFilter->EnumPins(&pEnum);
pEnum->Reset();
FAIL_TEST(pEnum->Next(1, &pGrabberInput, NULL));
pEnum.Release();
pSampleGrabberFilter->EnumPins(&pEnum);
pEnum->Reset();
pEnum->Skip(1);
FAIL_TEST(pEnum->Next(1, &pGrabberOutput, NULL));
pEnum.Release();
pNullFilter->EnumPins(&pEnum);
FAIL_TEST(pEnum->Reset());
FAIL_TEST(pEnum->Next(1, &pNullInputPin, NULL));
pEnum.Release();
DisplayProperties();
FAIL_TEST(pGraph->Connect(pCameraOutput, pGrabberInput));
FAIL_TEST(pGraph->Connect(pGrabberOutput, pNullInputPin));
if (deviceId == 2)
deviceId = deviceId;
if (FAILED(hr))
{
switch(hr)
{
case VFW_S_NOPREVIEWPIN :
break;
case E_FAIL :
break;
case E_INVALIDARG :
break;
case E_POINTER :
break;
}
hrinit = hr ;
return CAM_ERROR;
}
FAIL_TEST(pSampleGrabber->SetBufferSamples(TRUE));
FAIL_TEST(pSampleGrabber->SetOneShot(TRUE));
// AM_MEDIA_TYPE mt;
hrinit = pSampleGrabber->GetConnectedMediaType(&mt);
if (!FAILED(hrinit))
{
memcpy(&Vih,mt.pbFormat,sizeof(VIDEOINFOHEADER));
hrinit = pMediaControl->Run();
long evCode;
if (hrinit == S_FALSE)
hrinit = S_OK;
if (deviceId == 2)
deviceId = deviceId;
pSampleGrabber->SetCallback(&CB,1);
} else
{
return CAM_USED;
}
pMediaControl->Run();
/*
setting test
//IKsPropertySet *m_pKSProp;
CComPtr<IKsPropertySet> m_pKSProp;
hr = pDeviceFilter->QueryInterface(IID_IKsPropertySet, (void**)&m_pKSProp);
if (hr == S_OK)
{
DWORD dwSupported = 0;
hr = m_pKSProp->QuerySupported(PROPSETID_VIDCAP_VIDEOPROCAMP, KSPROPERTY_VIDEOPROCAMP_GAIN,
&dwSupported);
if(SUCCEEDED(hr) && dwSupported&KSPROPERTY_SUPPORT_SET)
{
KSPROPERTY_VIDEOPROCAMP_S ModeCaps;
memset(&ModeCaps,0,sizeof(KSPROPERTY_TUNER_MODE_CAPS_S));
DWORD cbBytes=0;
//ModeCaps.Property = KSPROPERTY_SUPPORT_SET;
ModeCaps.Value = 1;
ModeCaps.Flags = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL;
#define INSTANCEDATA_OF_PROPERTY_PTR(x) ((PKSPROPERTY((x))) + 1)
#define INSTANCEDATA_OF_PROPERTY_SIZE(x) (sizeof((x)) - sizeof(KSPROPERTY))
hr = m_pKSProp->Set(PROPSETID_VIDCAP_VIDEOPROCAMP,KSPROPERTY_VIDEOPROCAMP_COLORENABLE,
INSTANCEDATA_OF_PROPERTY_PTR(&ModeCaps),
INSTANCEDATA_OF_PROPERTY_SIZE(ModeCaps),
&ModeCaps, sizeof(ModeCaps));
}
}//*/
long evCode;
pMediaEvent->WaitForCompletion(2000, &evCode);
return 0;
}
#ifdef DRAW_FPS
u32 RRRRRR = 0;
#endif
int ARFrameGrabber::GrabFrame()
{
long evCode;
long size = 0;
pMediaControl->Run();
pMediaEvent->WaitForCompletion(INFINITE, &evCode);
//if (!CB.ImageCounter) return 0;
#ifdef DRAW_FPS
RRRRRR = 0;
if (CB.ImageCounter > 1 ) RRRRRR = CB.ImageCounter;
#endif
/*
u32 MAXWAIT = 100;
while ((!CB.ImageCounter) && MAXWAIT) {Sleep(1);MAXWAIT--;};
*/
if (!CB.ImageCounter ) return 0;
pSampleGrabber->GetCurrentBuffer(&size, NULL);
CB.ImageCounter = 0;
// if buffer is not the same size as before, create a new one
if (size && (size != bufferSize))
{
if (pBuffer)
CC_free(pBuffer);
bufferSize = size;
pBuffer = (long *)CC_malloc(bufferSize*sizeof(long));
}
pSampleGrabber->GetCurrentBuffer(&size, pBuffer);
return 1;
}
void ARFrameGrabber::BindFilter(int deviceId, IBaseFilter **pFilter)
{
if (deviceId < 0)
return;
*pFilter = NULL;
// 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)
{
WideCharToMultiByte(CP_ACP,0,var.bstrVal, -1, str, 2048, NULL, NULL);
if (index == deviceId)
{
FILTER_STATE State;
hr = pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter);
}
SysFreeString(var.bstrVal);
}
pBag->Release();
}
index++;
}
}
BOOL ARFrameGrabber::SetVideoControl(long mask, bool remove)
{
HRESULT hr;
return false; // ....
if ( hardwareFlipAvailable != 0 &&
!(hardwareFlipAvailable & mask))
return false;
if ((!remove && ( hardwareFlipSet & mask)) ||
( remove && !(hardwareFlipSet & mask)))
return true;
CComPtr<IAMVideoControl> videoControl;
CComPtr<IEnumPins> pEnum;
CComPtr<IPin> oPin;
if (S_OK == pDeviceFilter->QueryInterface(IID_IAMVideoControl, (void **)&videoControl) &&
S_OK == pDeviceFilter->EnumPins(&pEnum) &&
S_OK == pEnum->Reset() &&
S_OK == pEnum->Next(1, &oPin, NULL))
{
if (hardwareFlipAvailable == 0)
{
videoControl->GetCaps(oPin, &hardwareFlipAvailable);
hardwareFlipAvailable |= 0x80;
}
if (hardwareFlipAvailable & mask)
{
long mode = 0;
hr = videoControl->GetMode(oPin, &mode);
if (remove)
{
mode &= ~mask;
hardwareFlipSet &= ~mask;
} else
{
mode |= mask;
hardwareFlipSet |= mask;
}
hr = videoControl->SetMode(oPin, mode & hardwareFlipAvailable);
hr = videoControl->GetMode(oPin, &mode);
return true;
} else
{
hardwareFlipAvailable ^= mask;
return false;
}
} else
{
if (hardwareFlipAvailable == 0)
hardwareFlipAvailable |= 0x80;
}
return false;
}
void 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;
}
}
void MyDeleteMediaType(AM_MEDIA_TYPE *pmt)
{
if (pmt != NULL)
{
MyFreeMediaType(*pmt); // See FreeMediaType for the implementation.
CoTaskMemFree(pmt);
}
}
void ARFrameGrabber::DisplayProperties()
{
CComPtr<ISpecifyPropertyPages> pPages;
HRESULT hr;
IAMStreamConfig *pConfig;
AM_MEDIA_TYPE *pt_Media;
VIDEOINFOHEADER *pt_Vid;
// try doing ersolution change automatically
hr = pCameraOutput->QueryInterface(IID_IAMStreamConfig,(void**) &pConfig);
if (hr == S_OK)
{
hr = pConfig->GetFormat( &pt_Media );
pt_Vid = (VIDEOINFOHEADER *) pt_Media->pbFormat;
if (CAMERA_SpecifyedW == 160)
{
pt_Vid->bmiHeader.biWidth = 160;
pt_Vid->bmiHeader.biHeight = 120;//*/
} else
if (CAMERA_SpecifyedW == 352)
{
pt_Vid->bmiHeader.biWidth = 352;
pt_Vid->bmiHeader.biHeight = 288;//*/
} else
if (CAMERA_SpecifyedW == 640)
{
pt_Vid->bmiHeader.biWidth = 640;
pt_Vid->bmiHeader.biHeight = 480;//*/
} else
if (CAMERA_SpecifyedW == 800)
{
pt_Vid->bmiHeader.biWidth = 800;
pt_Vid->bmiHeader.biHeight = 600;//*/
} else
if (CAMERA_SpecifyedW == 1024)
{
pt_Vid->bmiHeader.biWidth = 1024;
pt_Vid->bmiHeader.biHeight = 768;//*/
} else
{
pt_Vid->bmiHeader.biWidth = 320;
pt_Vid->bmiHeader.biHeight = 240;
}
pt_Vid->bmiHeader.biBitCount = 24;
pt_Media->lSampleSize = pt_Vid->bmiHeader.biSizeImage = (pt_Vid->bmiHeader.biWidth * pt_Vid->bmiHeader.biHeight * pt_Vid->bmiHeader.biBitCount)>>3;
/*pt_Vid->bmiHeader.biWidth = 352;
pt_Vid->bmiHeader.biHeight = 288;//*/
/*pt_Vid->bmiHeader.biWidth = 640;
pt_Vid->bmiHeader.biHeight = 480;//*/
hr = pConfig->SetFormat( pt_Media );
pConfig->Release();
bufferSize = pt_Vid->bmiHeader.biWidth * pt_Vid->bmiHeader.biHeight;
if (pBuffer) CC_free(pBuffer);
if (bufferSize)
{
pBuffer = (long *)CC_malloc(bufferSize* sizeof(long));
}
else
pBuffer = NULL;
MyDeleteMediaType( pt_Media );
if (hr == S_OK )
return;
}
// automatic resolution change does'nt work, display property page
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::ReportError(char *msg)
{
MessageBox(NULL, msg, "ARFrameGrabber Error", MB_ICONSTOP);
}
class WEBCAM:public INPUT_IO
{
public:
ARFrameGrabber *grabber;
WORLD*pScene;
u32 DeviceID;
u32 LastTime;
u32 AvergageDT_x16;
u32 frameTime ;
u32 Locker ;
u32 UnplugCount ;
u32 UnplugWait;
u32 camOK;
int INIT (class WORLD*);
int FRAME (void);
int END (void);
IOTYPE GetType() {return IOtype_CAM;};
void *GetData(int dataIdx);
};
int WEBCAM::INIT(WORLD*pSc)
{
CoInitialize( NULL);
int defaultCam = 0;
LastTime = timeGetTime();
AvergageDT_x16 = 0;
grabber = new ARFrameGrabber();
Image.SX = Image.SY = 0;
if (*CurrWebCam)
{
defaultCam = GetWebCamByName(CurrWebCam, NULL);
if (defaultCam == -1)
defaultCam = 0;
}
if (grabber->Init(defaultCam) == CAM_USED)
{
UnplugWait = 63;
} else
if (grabber->hrinit != S_OK)
{
delete grabber;
grabber = new ARFrameGrabber();
Image.SX = Image.SY = 0;
grabber->Init(1);
if (grabber->hrinit != S_OK)
{
delete grabber;
grabber = new ARFrameGrabber();
Image.SX = Image.SY = 0;
grabber->Init(2);
if (grabber->hrinit != S_OK)
{
delete grabber;
grabber = new ARFrameGrabber();
Image.SX = Image.SY = 0;
grabber->Init(3);
if (grabber->hrinit != S_OK)
{
delete grabber;
grabber = new ARFrameGrabber();
Image.SX = Image.SY = 0;
grabber->Init(0);
if (grabber->hrinit != S_OK)
{
delete grabber;
grabber = NULL;
return 0;
}
}
}
}
}
if (grabber->hrinit != S_OK)
{
delete grabber;
grabber = NULL;
return 0;
}
if (grabber->Vih.bmiHeader.biWidth > 640)
{
delete grabber;
grabber = NULL;
return 0;
}
grabber->CB.ImageCounter = 1;
grabber->GrabFrame();
//memset(&Image, 0, sizeof(MAP));
if (grabber->Vih.bmiHeader.biWidth * grabber->Vih.bmiHeader.biHeight)
Image.SetSize(grabber->Vih.bmiHeader.biWidth, grabber->Vih.bmiHeader.biHeight);
pScene = pSc;
return 1;
}
u32 webcamInitTime = 0;
int WEBCAM::FRAME(void)
{
int i, j;
if (pScene->bManualBoot & 2) Locker = 8;
/* if (Locker)
{
Locker--;
return 1;
}*/
if (!grabber)
{
MAP SaveImage;
SaveImage = Image; SaveImage.staticBase = 1;
if (UnplugCount > 3)
{
UnplugCount++;
if ((UnplugCount & UnplugWait) != 0) return 1;
if (!INIT(pScene))
{
Image = SaveImage; Image.staticBase = 0;
grabber = NULL;
camOK = 0;
memset(Image.GetBase(),rand()&7,Image.PITCH * Image.SY * 4);
DRawTEXT_Soft_B_Centered((u8*)"Camera do not respond!!\nPlease restart or re-plug",(u32*)Image.GetBase(),Image.SX, Image.SY, 0xffff0000 + (rand()&7) + ((rand()&7)<<8));
return 1;
}
else
{
SaveImage.Delete();
if (ulAssociatedTextureIndex != -1)
pScene->DI->DestroyTexture(ulAssociatedTextureIndex);
ulAssociatedTextureIndex = pScene->DI->CreateTexture(&Image,ulColorMode);
UnplugCount = 0;
UnplugWait = 15;
frameTime = timeGetTime();
}
}
}
START_RASTER(WebCam);
if (grabber && grabber->GrabFrame())
{
camOK++;
UnplugCount = 0;
u32 curTime = timeGetTime();
if (!frameTime)
webcamInitTime = curTime;
else
webcamInitTime = curTime - ((curTime - frameTime)>>1);
frameTime = curTime;
AvergageDT_x16 -= AvergageDT_x16>>4;
AvergageDT_x16 += (curTime - LastTime)<<4;
LastTime = curTime;
int *dstPtr = Image.GetBase();
int *srcPtr = (int *)grabber->GetBuffer();
for (int y=0; y<Image.SY; y++)
{
for (int x=0; x<Image.SX; x++, srcPtr++, dstPtr++)
*dstPtr = *srcPtr | 0xFF000000;
dstPtr += Image.PITCH - Image.SX;
srcPtr += Image.PITCH - Image.SX;
}
if (pScene && pScene->WebCamXInvert)
{
if (!grabber->SetVideoControl(VideoControlFlag_FlipVertical))
{
s32 *ImageB,*ImageE;
ImageB = Image.GetBase();
ImageE = Image.GetBase() + Image.PITCH * Image.SY;
while (ImageB < ImageE)
{
s32 *RB,*RE;
RB = ImageB;
RE = ImageB + Image.SX - 1;
while (RB < RE)
{
s32 Swap;
Swap = *RB;
*RB = *RE;
*RE = Swap;
RB++;
RE--;
}
ImageB+=Image.PITCH;
}
}
} else
{
grabber->SetVideoControl(VideoControlFlag_FlipVertical, 1);
}
if (pScene && pScene->WebCamYInvert)
{
if (!grabber->SetVideoControl(VideoControlFlag_FlipHorizontal))
{
s32 *ImageB = Image.GetBase();
int PITCH = Image.PITCH;
int tmp;
int SX = Image.SX;
int SY = Image.SY;
for(int px=0; px<SX; px++)
for(int py=0; py<SY/2; py++)
{
tmp = *(ImageB + px + py*PITCH);
*(ImageB + px + py*PITCH) = *(ImageB + px + (SY-1-py)*PITCH);
*(ImageB + px + (SY-1-py)*PITCH) = tmp;
}
}
} else
{
grabber->SetVideoControl(VideoControlFlag_FlipHorizontal, 1);
}
{
s32 *ImageB,*ImageE;
ImageB = Image.GetBase();
ImageE = Image.GetBase() + Image.PITCH * Image.SY;
while (ImageB < ImageE)
{
*(ImageB++) |= 0xff000000 ;
*(ImageB++) |= 0xff000000 ;
*(ImageB++) |= 0xff000000 ;
*(ImageB++) |= 0xff000000 ;
}
}
#ifdef Draw_Histogram
s32 Histo[2048],*pX;
pX = Image.GetBase() + Image.PITCH * Image.SY/2;
for (s32 XCounter = 0 ; XCounter < Image.SX ; XCounter ++ , pX++)
Histo [XCounter]=(*pX &0xff) + ((*pX>>8) &0xff) + ((*pX>>16) &0xff);
DrawLine_Clip(&Image,
0,Image.SY>>1 ,
Image.SX ,Image.SY>>1 , 0xff0000);
for (s32 XCounter = 0 ; XCounter < Image.SX - 1; XCounter ++ )
DrawLine_Clip(&Image,
XCounter,(Histo [XCounter] >>2) ,
XCounter+1,(Histo [XCounter+1] >>2) , 0xff00);
#endif
#ifdef DRAW_FPS
char FrameRate[1024];
if (RRRRRR)
{
sprintf(FrameRate,"%d : %d",(s32)(256000.0f / (double)(AvergageDT_x16)),RRRRRR);
DRawTEXT_Soft_B((u8*)FrameRate,(u32*)Image.BASE,20,20, Image.PITCH , Image.SY, 0xffff0000);
}
else
{
sprintf(FrameRate,"%d",(s32)(256000.0f / (double)(AvergageDT_x16)));
DRawTEXT_Soft_B((u8*)FrameRate,(u32*)Image.BASE,20,20, Image.PITCH , Image.SY, 0xff00ff00);
}
#endif
STOP_RASTER(WebCam);
START_RASTER(Shots)
void FindHotSpot(MAP *pSrc,float Focale);
FindHotSpot(&Image,MediaFocale == 0.0 ? 2.2 : MediaFocale);
STOP_RASTER(Shots);//*/
return 1;
} else
{
static DWORD waitTime = 500;
if (timeGetTime() - frameTime > waitTime)
{
if (UnplugCount == 3)
{
if (grabber) delete grabber;
grabber = NULL;
camOK = 0;
Image.SetSize(Image.SX, Image.SY);
memset(Image.GetBase(),0,Image.PITCH * Image.SY * 4);
DRawTEXT_Soft_B_Centered((u8*)"Camera do not respond!!\nPlease restart or re-plug",(u32*)Image.GetBase(),Image.SX, Image.SY, 0xffff0000);
STOP_RASTER(WebCam);
UnplugCount ++;
waitTime = waitTime + 500;
return 1;
} else
UnplugCount ++;
} else
UnplugCount = 0;
}
STOP_RASTER(WebCam);
return 0;
}
int WEBCAM::END(void)
{
if (grabber) delete grabber;
Image.Delete();
return 0;
}
void *WEBCAM::GetData(int dataIdx)
{
switch (dataIdx)
{
case 3:
return (void *)(camOK > 1); // one frame waiting
}
return NULL;
}
INPUT_IO *WEBCAM_CREATE(WORLD *pScene,char *MediaName)
{
INPUT_IO *Ret;
u32 FFF = GetFileNameExtend((char *)MediaName) - 'CAM0';
Ret = (INPUT_IO *)new(WEBCAM);
strcpy((char*)Ret->MediaName,MediaName);
((WEBCAM *)Ret)->DeviceID = FFF;
Ret->dTotalTime = 0;
Ret->dAvgFramePerSecond = 30.0;
/* PHILIPPE : LOADING OPTIMIZE -> Create an unplugged camera */
if (0)
{
((WEBCAM *)Ret)->grabber = NULL;
((WEBCAM *)Ret)->Image.SetSize(320, 240, 1);
DRawTEXT_Soft_B_Centered((u8*)"Init Camera...",(u32*)((WEBCAM *)Ret)->Image.GetBase(),((WEBCAM *)Ret)->Image.SX, ((WEBCAM *)Ret)->Image.SY, 0xffff0000);
((WEBCAM *)Ret)->pScene = pScene;
((WEBCAM *)Ret)->UnplugCount = 0;
((WEBCAM *)Ret)->UnplugWait = 15;
((WEBCAM *)Ret)->camOK = 0;
((WEBCAM *)Ret)->frameTime = timeGetTime() - 200;
((WEBCAM *)Ret)->Locker = 0;
} else
/* PHILIPPE : LOADING OPTIMIZE -> instead of this */
Ret->INIT(pScene);
if (Ret->Image.SX == 0)
{
char String[1024];
delete Ret;
sprintf(String,"No Camera\n%s\nPlease Restart\nwith camera device",MediaName);
return ERROR_CREATE(String);
}
return Ret;
}
/*************************************************************************/
int GetWebCamNames(char compressors[][256], int *nbCompressors, int maxCompressors)
{
HRESULT hr;
ICreateDevEnum *pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void **)&pSysDevEnum);
if (FAILED(hr))
return hr;
// Obtain a class enumerator for the video compressor category.
IEnumMoniker *pEnumCat = NULL;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
*nbCompressors = 0;
if (hr == S_OK)
{
// Enumerate the monikers.
IMoniker *pMoniker = NULL;
ULONG cFetched;
while(*nbCompressors < maxCompressors && pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
{
IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
(void **)&pPropBag);
if (SUCCEEDED(hr))
{
// To retrieve the filter's friendly name, do the following:
VARIANT varName;
VariantInit(&varName);
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
if (SUCCEEDED(hr))
{
int net_len =WideCharToMultiByte(CP_ACP, 0,varName.bstrVal, -1, NULL, 0, NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, varName.bstrVal, -1, compressors[(*nbCompressors)++], net_len+1, NULL, NULL);
for (int uf=0; uf < NB_UNFRENDLY_CAMS; uf++)
{
if (!strnicmp(compressors[*nbCompressors-1], unfrendlyCams[uf], strlen(unfrendlyCams[uf])))
{
(*nbCompressors)--;
break;
}
}
}
VariantClear(&varName);
pPropBag->Release();
}
pMoniker->Release();
}
pEnumCat->Release();
}
pSysDevEnum->Release();
return *nbCompressors;
}
int GetWebCamByName(char *compressorsName)
{
return GetWebCamByName(compressorsName, NULL);
}
int GetWebCamByName(char *compressorsName, IBaseFilter **FilterPtr)
{
HRESULT hr;
char filterName[256];
int resIndex = -1;
ICreateDevEnum *pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void **)&pSysDevEnum);
if (FAILED(hr))
return false;
// Obtain a class enumerator for the video compressor category.
IEnumMoniker *pEnumCat = NULL;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
int currIndex = -1;
if (hr == S_OK)
{
// Enumerate the monikers.
IMoniker *pMoniker = NULL;
ULONG cFetched;
while(resIndex != 1 && pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
{
IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
(void **)&pPropBag);
if (SUCCEEDED(hr))
{
// To retrieve the filter's friendly name, do the following:
VARIANT varName;
VariantInit(&varName);
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
if (SUCCEEDED(hr))
{
currIndex++;
int net_len =WideCharToMultiByte(CP_ACP, 0,varName.bstrVal, -1, NULL, 0, NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, varName.bstrVal, -1, filterName, net_len+1, NULL, NULL);
if (!strcmp(filterName, compressorsName))
{
if (FilterPtr != NULL)
hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)FilterPtr);
resIndex = currIndex;
}
}
VariantClear(&varName);
pPropBag->Release();
}
pMoniker->Release();
}
pEnumCat->Release();
}
pSysDevEnum->Release();
return resIndex;
}
void PropertyPageCall(void *params)
{
IBaseFilter *filter = (IBaseFilter *)params;
HRESULT hr = E_FAIL;
CComPtr<ISpecifyPropertyPages> pPages;
hr = filter->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pPages);
CAUUID caGUID;
pPages->GetPages(&caGUID);
OleCreatePropertyFrame(
NULL,
0,
0,
L"Property Sheet",
1,
(IUnknown **)&(filter),
caGUID.cElems,
caGUID.pElems,
0,
0,
NULL);
CoTaskMemFree(caGUID.pElems);
pPages.Release();
}
BOOL GetWebCamFilterPropertyByName(char *name, bool openPage)
{
HRESULT hr = E_FAIL;
if (!*name)
return hr;
IBaseFilter *filter;
if (GetWebCamByName(name, &filter) != -1)
{
CComPtr<ISpecifyPropertyPages> pPages;
hr = filter->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pPages);
if (SUCCEEDED(hr))
{
pPages.Release();
if (openPage)
_beginthread(PropertyPageCall, 0, filter);
}
}
return hr == S_OK;
}