Hello!
I'm programing with 3 webcams to build preview videos and then take 3 pictures from each one. My developing environment is visual studio c++ 2010 express/ clr/ windows forms app.
I can already successfully get three preview videos on my pc. But I'm facing with a big problem: when I connect my webcams to another computer using the same code, the capturing has an error (program breaks or showing videos in a different order).
After I tested this on several computers,
I finally found the reason. It is when the webcams are connected to another pc, the new pc may get a new order of them when the new pc counts the devices (Which means they were on my pc as usb-device 1, 2, 3; they are on the new pc as usb-device 2, 1, 3). But I need to use the webcams in the order like before. Webcam1 on pictureBox1, webcam2 on pBox2, and webcam3 on pBox3. And I would like my code to be generally useful, whatever on which pc and with any webcams.
What also means, I want to choose the webcams in an "user-wanted" order on the window(of 3 pictureBoxes). Now I'm thinking of one way to solve this, namely to put a comboBox under each pictureBox, which are used to choose the device for each pictureBox. But I don't know how to realize that. Could you please help me? Or do you have a better idea to prevent the problem???
What may also be very important: Could it be wrong with my counting devices method in the CamShow.cpp? Should I make some correctors there?
Any answers would be appreciated!
My recently code is:
Form.h:
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
CamShow test1;
CamShow test2;
CamShow test3;
button1->Enabled=false;
hr = test1.InitComLib();
hr = test1.CaptureVideo(1);
System::Drawing::Rectangle rc = pictureBox1->ClientRectangle;
hr = test1.pVW->put_Owner(OAHWND(this->pictureBox1->Handle.ToInt64()));
hr = test1.pVW->put_WindowStyle( WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN );
hr = test1.pVW->SetWindowPosition( 0, 0, rc.Right, rc.Bottom );
hr = test1.pMC->Run();
test1.ControlRelease();
test1.EventRelease();
test1.GraphBuilderRelease();
test1.CoUnini();
hr = test2.InitComLib();
hr = test2.CaptureVideo(2);
System::Drawing::Rectangle rc = pictureBox1->ClientRectangle;
hr = test2.pVW->put_Owner(OAHWND(this->pictureBox1->Handle.ToInt64()));
hr = test2.pVW->put_WindowStyle( WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN );
hr = test2.pVW->SetWindowPosition( 0, 0, rc.Right, rc.Bottom );
hr = test2.pMC->Run();
test2.ControlRelease();
test2.EventRelease();
test2.GraphBuilderRelease();
test2.CoUnini();
hr = test3.InitComLib();
hr= test3.CaptureVideo(3);
System::Drawing::Rectangle rc = pictureBox1->ClientRectangle;
hr = test3.pVW->put_Owner(OAHWND(this->pictureBox1->Handle.ToInt64()));
hr = test3.pVW->put_WindowStyle( WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN );
hr = test3.pVW->SetWindowPosition( 0, 0, rc.Right, rc.Bottom );
hr = test3.pMC->Run();
test3.ControlRelease();
test3.EventRelease();
test3.GraphBuilderRelease();
test3.CoUnini();
}
CamShow.cpp:
I give the most relevant code-sections to my problem here. And the declarations of variables functions are in CamShow.h, which I don't need to copy here for you I think ;).
#include "stdafx.h"
#include <DShow.h>
#include <Windows.h>
#include <comdef.h>
#include "CamShow.h"
CamShow::CamShow() {...}
CamShow::~CamShow() {}
HRESULT CamShow::InitComLib()
{
HRESULT hr = NULL;
hr = CoInitialize(NULL);
return hr;
}
HRESULT CamShow::CaptureVideo(int NO)
{
HRESULT hr;
IBaseFilter *pSrcFilter=NULL;
hr = GetInterfaces();
if (FAILED(hr))
{
Msg(TEXT("error get interfaces: hr=0x%x"), hr);
return hr;
}
hr = pCGB2->SetFiltergraph(pGraphBuilder);
if (FAILED(hr))
{
Msg(TEXT("error Set Filtergraph: hr=0x%x"), hr);
return hr;
}
hr = FindCaptureDevice(&pSrcFilter, NO);
if (FAILED(hr))
{
return hr;
}
hr = pGraphBuilder->AddFilter(pSrcFilter, L"Capture Filter");
if (FAILED(hr))
{
Msg(TEXT("Couldn't add the capture filter to the graph! hr=0x%x\r\n\r\n")
TEXT("If you have a working video capture device, please make sure\r\n")
TEXT("that it is connected and is not being used by another application.\r\n\r\n")
TEXT("The sample will now close."), hr);
pSrcFilter->Release();
return hr;
}
hr = pCGB2->RenderStream (&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pSrcFilter, NULL, NULL);
if (FAILED(hr))
{
Msg(TEXT("Couldn't render the video capture stream. hr=0x%x\r\n"), hr);
pSrcFilter->Release();
return hr;
}
pSrcFilter->Release();
hr = intSetupVideoWindow();
if (FAILED(hr))
{
Msg(TEXT"Couldn't initialize video window! hr=0x%x"),hr);
return hr;
}
hr = pMC->Run();
if (FAILED(hr))
{
Msg(TEXT("Couldn't run the graph! hr=0x%x"), hr);
return hr;
}
psCurrent = Running;
return S_OK;
}
HRESULT CamShow::FindCaptureDevice(IBaseFilter ** ppSrcFilter, int NO)
{
HRESULT hr = S_OK;
IBaseFilter * pSrc = NULL;
IMoniker* pMoniker = NULL;
ULONG cFetched;
int DevNo=0;
IEnumMoniker *pClassEnum = NULL;
ICreateDevEnum *pDevEnum =NULL;
if (!ppSrcFilter) return E_POINTER;
hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
IID_ICreateDevEnum, (void **) &pDevEnum);
if (FAILED(hr))
{
Msg(TEXT("Couldn't create system enumerator! hr=0x%x"), hr); }
if (SUCCEEDED(hr))
{
hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pClassEnum, 0);
if (FAILED(hr))
{
Msg(TEXT("Couldn't create class enumerator! hr=0x%x"), hr); }
pDevEnum->Release();
}
if (SUCCEEDED(hr))
{
{
MessageBox(ghApp,TEXT("No video capture device was detected.\r\n\r\n")
TEXT("This sample requires a video capture device, such as a USB WebCam,\r\n")
TEXT("to be installed and working properly. The sample will now close."),
TEXT("No Video Capture Hardware"), MB_OK | MB_ICONINFORMATION);
hr = E_FAIL;
}
}
while (pClassEnum->Next(1, &pMoniker, &cFetched) == S_OK)
{
IPropertyBag *pBag = NULL;
BSTR sName;
VARIANT var;
VariantInit(&var);
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
hr = pBag->Read(L"FriendlyName", &var, 0);
sName = var.bstrVal;
DevNo++;
VariantClear(&var);
if (SUCCEEDED(hr))
{
if (DevNo==NO)
{
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void **)&pSrc);
if (FAILED(hr))
return hr;
pBag->Release();
pMoniker->Release();
break;
}
}
}
if (SUCCEEDED(hr))
{
*ppSrcFilter = pSrc;
(*ppSrcFilter)->AddRef();
}
return hr;
}
......(Other functions)
I hope I've explained my problem clearly. If anything is not clear for you, just tell me and I'm going to answer you and improve my question.
Thanks for helping!