vendredi 8 août 2014

Visual c ++ - DirectShow, capture d'images fixes - Stack Overflow


i'm not experienced in Windows programming, i try to capture a Still Image from a WebCam using DirectShow. I wrote a small application based on CommandCam.cpp, which can be found here:


http://batchloaf.wordpress.com/commandcam/


I basically added the code that can be found here:


http://msdn.microsoft.com/en-us/library/windows/desktop/dd318622%28v=vs.85%29.aspx


But the call to pBuilder->FindPin(pCap, PINDIR_OUTPUT, &PIN_CATEGORY_STILL, ... fails and i can't get the Pin for the Still Image.


I doubt that because using other Webcam programs i can get a Still Image from my Microsoft LifeCam Studio.


I wonder what i am doing wrong? I tried placing the call in different places in the application but it never succeeded.


Thanks for any hints, Torsten.


The relevant part of the code is this: // Get video input device name hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag)); VariantInit(&var); hr = pPropBag->Read(L"FriendlyName", &var, 0); fprintf(stderr, "Capture device: %ls\n", var.bstrVal); VariantClear(&var);


// Create capture filter and add to graph
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
if (hr != S_OK) exit_message("Could not create capture filter", 1);

// Add capture filter to graph
hr = pGraph->AddFilter(pCap, L"Capture Filter");
if (hr != S_OK) exit_message("Could not add capture filter to graph", 1);

// Create sample grabber filter
hr = CoCreateInstance(CLSID_SampleGrabber, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter,
(void**)&pSampleGrabberFilter);
if (hr != S_OK)
exit_message("Could not create Sample Grabber filter", 1);

// Query the ISampleGrabber interface of the sample grabber filter
hr = pSampleGrabberFilter->QueryInterface(
DexterLib::IID_ISampleGrabber, (void**)&pSampleGrabber);
if (hr != S_OK)
exit_message("Could not get ISampleGrabber interface to sample grabber filter", 1);

// Enable sample buffering in the sample grabber filter
hr = pSampleGrabber->SetBufferSamples(TRUE);
if (hr != S_OK)
exit_message("Could not enable sample buffering in the sample grabber", 1);

// Set media type in sample grabber filter
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
mt.majortype = MEDIATYPE_Video;
mt.subtype = MEDIASUBTYPE_RGB24;
hr = pSampleGrabber->SetMediaType((DexterLib::_AMMediaType *)&mt);
if (hr != S_OK)
exit_message("Could not set media type in sample grabber", 1);

// Add sample grabber filter to filter graph
hr = pGraph->AddFilter(pSampleGrabberFilter, L"SampleGrab");
if (hr != S_OK)
exit_message("Could not add Sample Grabber to filter graph", 1);

// Create Null Renderer filter
hr = CoCreateInstance(CLSID_NullRenderer, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter,
(void**)&pNullRenderer);
if (hr != S_OK)
exit_message("Could not create Null Renderer filter", 1);

// Add Null Renderer filter to filter graph
hr = pGraph->AddFilter(pNullRenderer, L"NullRender");
if (hr != S_OK)
exit_message("Could not add Null Renderer to filter graph", 1);

// Connect up the filter graph's capture stream
hr = pBuilder->RenderStream(
&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
pCap, pSampleGrabberFilter, pNullRenderer);
if (hr != S_OK)
exit_message("Could not render capture video stream", 1);


hr = pBuilder->RenderStream(
&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
pCap, NULL, NULL);
if (hr != S_OK && hr != VFW_S_NOPREVIEWPIN)
exit_message("Could not render preview video stream", 1);

// Get media control interfaces to graph builder object
hr = pGraph->QueryInterface(IID_IMediaControl,
(void**)&pMediaControl);
if (hr != S_OK) exit_message("Could not get media control interface", 1);

// Run graph
while(1)
{
hr = pMediaControl->Run();

// Hopefully, the return value was S_OK or S_FALSE
if (hr == S_OK) break; // graph is now running
if (hr == S_FALSE) continue; // graph still preparing to run

// If the Run function returned something else,
// there must be a problem
fprintf(stderr, "Error: %u\n", hr);
exit_message("Could not run filter graph", 1);
}

Sleep(2000);

// get the StillImage Pin
hr = pCap->QueryInterface(IID_IAMVideoControl, (void**)&pAMVidControl);
if (hr != S_OK) exit_message("Could not get IAMVideoControl", 1);

hr = pBuilder->FindPin(pCap, PINDIR_OUTPUT, &PIN_CATEGORY_STILL, NULL, FALSE, 0, &pPin);
if (hr != S_OK)
exit_message("Could not get Pin of category StillImage", 1);

hr = pAMVidControl->SetMode(pPin, VideoControlFlag_Trigger);
if (hr != S_OK) exit_message("Could set mode VideoControlFlag_Trigger", 1);



Some video capture device source filters do not expose a still image capture pin.


Did you try using the EnumPins method to find whether it actually has one, or if there is just a preview pin?


You could also use GraphEdit to have a look at the filter's pins.


If the device only has a preview pin, you will have to use that to grab your image. You can use the Smart Tee Filter to split your graph into preview and capture.



i'm not experienced in Windows programming, i try to capture a Still Image from a WebCam using DirectShow. I wrote a small application based on CommandCam.cpp, which can be found here:


http://batchloaf.wordpress.com/commandcam/


I basically added the code that can be found here:


http://msdn.microsoft.com/en-us/library/windows/desktop/dd318622%28v=vs.85%29.aspx


But the call to pBuilder->FindPin(pCap, PINDIR_OUTPUT, &PIN_CATEGORY_STILL, ... fails and i can't get the Pin for the Still Image.


I doubt that because using other Webcam programs i can get a Still Image from my Microsoft LifeCam Studio.


I wonder what i am doing wrong? I tried placing the call in different places in the application but it never succeeded.


Thanks for any hints, Torsten.


The relevant part of the code is this: // Get video input device name hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag)); VariantInit(&var); hr = pPropBag->Read(L"FriendlyName", &var, 0); fprintf(stderr, "Capture device: %ls\n", var.bstrVal); VariantClear(&var);


// Create capture filter and add to graph
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
if (hr != S_OK) exit_message("Could not create capture filter", 1);

// Add capture filter to graph
hr = pGraph->AddFilter(pCap, L"Capture Filter");
if (hr != S_OK) exit_message("Could not add capture filter to graph", 1);

// Create sample grabber filter
hr = CoCreateInstance(CLSID_SampleGrabber, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter,
(void**)&pSampleGrabberFilter);
if (hr != S_OK)
exit_message("Could not create Sample Grabber filter", 1);

// Query the ISampleGrabber interface of the sample grabber filter
hr = pSampleGrabberFilter->QueryInterface(
DexterLib::IID_ISampleGrabber, (void**)&pSampleGrabber);
if (hr != S_OK)
exit_message("Could not get ISampleGrabber interface to sample grabber filter", 1);

// Enable sample buffering in the sample grabber filter
hr = pSampleGrabber->SetBufferSamples(TRUE);
if (hr != S_OK)
exit_message("Could not enable sample buffering in the sample grabber", 1);

// Set media type in sample grabber filter
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
mt.majortype = MEDIATYPE_Video;
mt.subtype = MEDIASUBTYPE_RGB24;
hr = pSampleGrabber->SetMediaType((DexterLib::_AMMediaType *)&mt);
if (hr != S_OK)
exit_message("Could not set media type in sample grabber", 1);

// Add sample grabber filter to filter graph
hr = pGraph->AddFilter(pSampleGrabberFilter, L"SampleGrab");
if (hr != S_OK)
exit_message("Could not add Sample Grabber to filter graph", 1);

// Create Null Renderer filter
hr = CoCreateInstance(CLSID_NullRenderer, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter,
(void**)&pNullRenderer);
if (hr != S_OK)
exit_message("Could not create Null Renderer filter", 1);

// Add Null Renderer filter to filter graph
hr = pGraph->AddFilter(pNullRenderer, L"NullRender");
if (hr != S_OK)
exit_message("Could not add Null Renderer to filter graph", 1);

// Connect up the filter graph's capture stream
hr = pBuilder->RenderStream(
&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
pCap, pSampleGrabberFilter, pNullRenderer);
if (hr != S_OK)
exit_message("Could not render capture video stream", 1);


hr = pBuilder->RenderStream(
&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
pCap, NULL, NULL);
if (hr != S_OK && hr != VFW_S_NOPREVIEWPIN)
exit_message("Could not render preview video stream", 1);

// Get media control interfaces to graph builder object
hr = pGraph->QueryInterface(IID_IMediaControl,
(void**)&pMediaControl);
if (hr != S_OK) exit_message("Could not get media control interface", 1);

// Run graph
while(1)
{
hr = pMediaControl->Run();

// Hopefully, the return value was S_OK or S_FALSE
if (hr == S_OK) break; // graph is now running
if (hr == S_FALSE) continue; // graph still preparing to run

// If the Run function returned something else,
// there must be a problem
fprintf(stderr, "Error: %u\n", hr);
exit_message("Could not run filter graph", 1);
}

Sleep(2000);

// get the StillImage Pin
hr = pCap->QueryInterface(IID_IAMVideoControl, (void**)&pAMVidControl);
if (hr != S_OK) exit_message("Could not get IAMVideoControl", 1);

hr = pBuilder->FindPin(pCap, PINDIR_OUTPUT, &PIN_CATEGORY_STILL, NULL, FALSE, 0, &pPin);
if (hr != S_OK)
exit_message("Could not get Pin of category StillImage", 1);

hr = pAMVidControl->SetMode(pPin, VideoControlFlag_Trigger);
if (hr != S_OK) exit_message("Could set mode VideoControlFlag_Trigger", 1);


Some video capture device source filters do not expose a still image capture pin.


Did you try using the EnumPins method to find whether it actually has one, or if there is just a preview pin?


You could also use GraphEdit to have a look at the filter's pins.


If the device only has a preview pin, you will have to use that to grab your image. You can use the Smart Tee Filter to split your graph into preview and capture.


0 commentaires:

Enregistrer un commentaire