#include #define DEFAULT_CAPTURE_WIDTH 320 #define DEFAULT_CAPTURE_HEIGHT 240 #define DEFAULT_CAPTURE_RATE 15 IplImage* DsCaptureFilter::acquiredImage = 0; DsCaptureFilter::DsCaptureFilter(char* s) : CBaseVideoRenderer(__uuidof(CLSID_Sampler), NAME("Frame Sampler"), 0, 0), Filter(s) { graph = NULL; mediaControl = NULL; mediaEvent = NULL; captureWidth = DEFAULT_CAPTURE_WIDTH; captureHeight = DEFAULT_CAPTURE_HEIGHT; captureRate = DEFAULT_CAPTURE_RATE; started = false; } DsCaptureFilter::~DsCaptureFilter() { // Do not forget to release after use if(mediaControl) mediaControl->Release(); if(graph) graph->Release(); if(newFrameEvent) CloseHandle(newFrameEvent); CoUninitialize(); } // Very basic setup of capture filter, we should do error checking bool DsCaptureFilter::initialize() { IBaseFilter* sourceFilter = NULL; IPin* sourcePin = NULL; HRESULT hr = CoInitialize(0); hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC,IID_IGraphBuilder, (void **)&graph); hr = graph->QueryInterface(IID_IMediaControl, (void **)&mediaControl); //sampler = new Sampler(0, &hr); IPin* renderPin = NULL; hr = this->FindPin(L"In", &renderPin); hr = graph->AddFilter((IBaseFilter*)this, L"Sampler"); if(strcmp(source, "cam") == 0) // Capture from camera { ICreateDevEnum* devs = NULL; hr = CoCreateInstance (CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC, IID_ICreateDevEnum, (void **) &devs); IEnumMoniker* cams = NULL; hr = devs?devs->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &cams, 0):0; IMoniker* mon = NULL; hr = cams?cams->Next (1, &mon, 0):0; hr = mon?mon->BindToObject(0,0,IID_IBaseFilter, (void**)&sourceFilter):0; hr = graph->AddFilter(sourceFilter, L"Capture Source"); } else // Capture from AVI { WCHAR filename[256]; MultiByteToWideChar(0, 0, source, -1, filename, sizeof(filename)); hr = graph->AddSourceFilter(filename, L"File Source", &sourceFilter); hr = sourceFilter?sourceFilter->FindPin(L"Output", &sourcePin):0; hr = graph?graph->QueryInterface(IID_IMediaEvent, (void **)&mediaEvent):0; hr = graph?graph->QueryInterface(IID_IMediaSeeking, (void **)&mediaSeek):0; } IEnumPins* pins = NULL; hr = sourceFilter?sourceFilter->EnumPins(&pins):0; hr = pins?pins->Next(1,&sourcePin, 0):0; hr = graph->Connect(sourcePin, renderPin); newFrameEvent = CreateEvent(0, FALSE, FALSE, "NewFrameEvent"); return true; } void DsCaptureFilter::acquireImage(void *param) { /* while(1) { if(capture) { acquiredImage = cvQueryFrame( capture ); // rewind the movie. if(!acquiredImage) cvSetCaptureProperty(capture, CV_CAP_PROP_POS_MSEC, 0); Sleep(32); } else { _endthread(); } } */ } void DsCaptureFilter::process(IplImage *frame) { Filter::process(frame); acquiredImage = NULL; destination = NULL; } void DsCaptureFilter::getParameters(ParameterMap& pMap) { pMap[std::string("source")] = std::string(source); pMap[std::string("format")] = toString(captureWidth)+"x"+ toString(captureHeight)+"@"+ toString(captureRate); } void DsCaptureFilter::setParameter(const char *name, const char *value) { // I dont like this, the user is not notified about any errors that occur // during this very fragile process of setting up capture... // Perhaps we should have a CTouchScreen initialize() which sets up the capture // filter to remedy this. (Nick) if(!graph) { if(strcmp(name, "source") == 0) { strcpy(source, value); initialize(); } if(strcmp(name, "format") == 0) { sscanf(value, "%dx%d@%d", &captureWidth, &captureHeight, &captureRate); } } } bool DsCaptureFilter::isRunning() { return destination != NULL; } void DsCaptureFilter::kernel() { HRESULT hr; long eventCode; LONG_PTR param1, param2; if(!started) { mediaControl->Run(); started = true; } destination = NULL; if(mediaEvent) { mediaEvent->GetEvent(&eventCode, ¶m1, ¶m2, 0); // if we have reached the end of the video, start it over if(eventCode == EC_COMPLETE) { LONGLONG cur = 0; hr = mediaSeek->SetPositions(&cur, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning); hr = mediaControl->Run(); } mediaEvent->FreeEventParams(eventCode, param1, param2); } // Wait for a frame to arrive DWORD dw = WaitForSingleObject(newFrameEvent, INFINITE); destination = acquiredImage; } HRESULT DsCaptureFilter::CheckMediaType(const CMediaType *media ) { VIDEOINFO* vi; if(!IsEqualGUID( *media->Subtype(), MEDIASUBTYPE_RGB24) || !(vi = (VIDEOINFO *)media->Format()) ) return E_FAIL; // If capturing from camera, specify the format if(strcmp(source, "cam") == 0) { if(vi->bmiHeader.biWidth != captureWidth) return E_FAIL; if(vi->bmiHeader.biHeight != captureHeight) return E_FAIL; } DsCaptureFilter::acquiredImage = ::cvCreateImageHeader(cvSize(vi->bmiHeader.biWidth, vi->bmiHeader.biHeight), 8, 3); return S_OK; } HRESULT DsCaptureFilter::DoRenderSample(IMediaSample *sample) { BYTE* data; sample->GetPointer(&data); DsCaptureFilter::acquiredImage->imageData = (char*)data; SetEvent(newFrameEvent); return S_OK; }