DShowCameraDeviceInteral (CameraDevice* const owner_, const ComSmartPtr <ICaptureGraphBuilder2>& captureGraphBuilder_, const ComSmartPtr <IBaseFilter>& filter_, int minWidth, int minHeight, int maxWidth, int maxHeight) : owner (owner_), captureGraphBuilder (captureGraphBuilder_), filter (filter_), ok (false), imageNeedsFlipping (false), width (0), height (0), activeUsers (0), recordNextFrameTime (false), previewMaxFPS (60) { HRESULT hr = graphBuilder.CoCreateInstance (CLSID_FilterGraph); if (FAILED (hr)) return; hr = captureGraphBuilder->SetFiltergraph (graphBuilder); if (FAILED (hr)) return; hr = graphBuilder.QueryInterface (mediaControl); if (FAILED (hr)) return; { ComSmartPtr <IAMStreamConfig> streamConfig; hr = captureGraphBuilder->FindInterface (&PIN_CATEGORY_CAPTURE, 0, filter, IID_IAMStreamConfig, (void**) streamConfig.resetAndGetPointerAddress()); if (streamConfig != nullptr) { getVideoSizes (streamConfig); if (! selectVideoSize (streamConfig, minWidth, minHeight, maxWidth, maxHeight)) return; } } hr = graphBuilder->AddFilter (filter, _T("Video Capture")); if (FAILED (hr)) return; hr = smartTee.CoCreateInstance (CLSID_SmartTee); if (FAILED (hr)) return; hr = graphBuilder->AddFilter (smartTee, _T("Smart Tee")); if (FAILED (hr)) return; if (! connectFilters (filter, smartTee)) return; ComSmartPtr <IBaseFilter> sampleGrabberBase; hr = sampleGrabberBase.CoCreateInstance (CLSID_SampleGrabber); if (FAILED (hr)) return; hr = sampleGrabberBase.QueryInterface (IID_ISampleGrabber, sampleGrabber); if (FAILED (hr)) return; { AM_MEDIA_TYPE mt = { 0 }; mt.majortype = MEDIATYPE_Video; mt.subtype = MEDIASUBTYPE_RGB24; mt.formattype = FORMAT_VideoInfo; sampleGrabber->SetMediaType (&mt); } callback = new GrabberCallback (*this); hr = sampleGrabber->SetCallback (callback, 1); hr = graphBuilder->AddFilter (sampleGrabberBase, _T("Sample Grabber")); if (FAILED (hr)) return; ComSmartPtr <IPin> grabberInputPin; if (! (getPin (smartTee, PINDIR_OUTPUT, smartTeeCaptureOutputPin, "capture") && getPin (smartTee, PINDIR_OUTPUT, smartTeePreviewOutputPin, "preview") && getPin (sampleGrabberBase, PINDIR_INPUT, grabberInputPin))) return; hr = graphBuilder->Connect (smartTeePreviewOutputPin, grabberInputPin); if (FAILED (hr)) return; AM_MEDIA_TYPE mt = { 0 }; hr = sampleGrabber->GetConnectedMediaType (&mt); VIDEOINFOHEADER* pVih = (VIDEOINFOHEADER*) (mt.pbFormat); width = pVih->bmiHeader.biWidth; height = pVih->bmiHeader.biHeight; ComSmartPtr <IBaseFilter> nullFilter; hr = nullFilter.CoCreateInstance (CLSID_NullRenderer); hr = graphBuilder->AddFilter (nullFilter, _T("Null Renderer")); if (connectFilters (sampleGrabberBase, nullFilter) && addGraphToRot()) { activeImage = Image (Image::RGB, width, height, true); loadingImage = Image (Image::RGB, width, height, true); ok = true; } }
DSVideoDevice::DSVideoDevice(int id, const std::wstring & devName, IFilterGraph2* graph, ICaptureGraphBuilder2* capture, IMoniker* moniker) : d_(new Impl(id, devName, graph)) { //add a filter for the device HRESULT hr = graph->AddSourceFilterForMoniker(moniker, 0, d_->filtername.c_str(), &d_->sourcefilter); if (hr != S_OK) throw hr; //create a samplegrabber filter for the device hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&d_->samplegrabberfilter); if (hr < 0) throw hr; //set mediatype on the samplegrabber hr = d_->samplegrabberfilter->QueryInterface(IID_ISampleGrabber, (void**)&d_->samplegrabber); if (hr != S_OK) throw hr; const std::wstring sgFilterName = L"SampleGrabberFilter_" + d_->filtername; graph->AddFilter(d_->samplegrabberfilter, sgFilterName.c_str()); //set the media type AM_MEDIA_TYPE mt; memset(&mt, 0, sizeof(AM_MEDIA_TYPE)); mt.majortype = MEDIATYPE_Video; mt.subtype = MEDIASUBTYPE_RGB24; // setting the above to 32 bits fails consecutive Select for some reason // and only sends one single callback (flush from previous one ???) // must be deeper problem. 24 bpp seems to work fine for now. hr = d_->samplegrabber->SetMediaType(&mt); if (hr != S_OK) throw hr; //add the callback to the samplegrabber hr = d_->samplegrabber->SetCallback(d_->callbackhandler, 0); if (hr != S_OK) throw hr; //set the null renderer hr = CoCreateInstance(CLSID_NullRenderer, NULL,CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**) &d_->nullrenderer); if (hr < 0) throw hr; const std::wstring nrFilterName = L"NullRenderer_" + d_->filtername; graph->AddFilter(d_->nullrenderer, nrFilterName.c_str()); //set the render path #ifdef DEBUG_RENDERER hr = capture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, d_->sourcefilter, d_->samplegrabberfilter, NULL); #else hr = capture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, d_->sourcefilter, d_->samplegrabberfilter, d_->nullrenderer); #endif if (hr < 0) throw hr; //#undef max // to get std::limits to work //long long start = 0; long long stop = MAXLONGLONG; //std::numeric_limits<long long>::max(); //if the stream is started, start capturing immediately //hr = capture->ControlStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, d_->sourcefilter, &start, &stop, 1, 2); hr = capture->ControlStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, d_->sourcefilter, NULL, &stop, 1, 2); if (hr < 0) throw hr; #ifdef REGISTER_FILTERGRAPH // Add our graph to the running object table, which will allow // the GraphEdit application to "spy" on our graph hr = addGraphToRot(d_->graph, &d_->dwGraphRegister); if (FAILED(hr)) { //Msg(TEXT("Failed to register filter graph with ROT! hr=0x%x"), hr); //g_dwGraphRegister = 0; } #endif }