关于使用DirectShow 同时控制两个乃至多个USB相机

关于使用DirectShow 同时控制两个乃至多个USB相机

class CLeftSampleGrabberCB   : public ISampleGrabberCB{
public:
	int  lWidth;
	int  lHeight;
public:

	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) {
		return 0;
	}
	STDMETHODIMP BufferCB(double dblSampleTime, BYTE * pBuffer, long lBufferSize) {
		//timer.End();
		
		if (!pBuffer)return E_POINTER;
		if(leftEvent){

			CSingleLock singleLock(&Mutex);
			singleLock.Lock() ;
			writeFile(leftCycle,leftLocation ,0 ,pBuffer, lBufferSize);
			leftEvent = false ;
			if ()
			{
			}
			singleLock.Unlock() ;
		}
		return 0;
	}

public:
	int writeFile(int cycle  ,double location,int dir ,BYTE * pBuffer, long lBufferSize){
		FILE * fp = NULL;
		CString str ; 
		str.Format("C:\\BScanData\\ImageData\\data.ckJpg");

		fp = fopen(str, "ab+");
		if (fp == NULL)
		{
			AfxMessageBox("打开文件失败");
			return -1;
		}
		int dataSize  = lBufferSize ;
		//数据写入文件 
		fwrite(&cycle, sizeof(int), 1, fp);
		fwrite(&lWidth, sizeof(int), 1, fp);
		fwrite(&lHeight, sizeof(int), 1, fp);
		fwrite(&dataSize, sizeof(int), 1, fp);
		fwrite(&dir, sizeof(int), 1, fp);
		fwrite(&location, sizeof(double), 1, fp);
		fwrite(pBuffer, 1, lBufferSize, fp);
		//释放内存空间
		fclose(fp);
		return 0 ;
	}
};

上述为从单个相机的视频流中取出一帧图像 , 参考Palycap 例子 , 在得到相机的控制指针后 ,加入 ,

	hr = m_pGrabber->SetCallback(&mLeftCB, 1);
	hr = m_pGrabber->SetBufferSamples(FALSE);
	hr = m_pGrabber->SetOneShot(FALSE);

其中mleftcb 为上面的类定义的对象 , ,一开始我是在一个相机的情况下 ,进行的 ,测试 ,
在我直接将使用上述的类定义俩对象时,同时控制两个相机 进行抓图 ,这

	if (m_RailType == LeftRail)
	{
		mLeftCB.lWidth = vih->bmiHeader.biWidth;
		mLeftCB.lHeight = vih->bmiHeader.biHeight;
		hr = m_pGrabber->SetCallback(&mLeftCB, 1);
	}else{
		mRightCB.lWidth = vih->bmiHeader.biWidth;
		mRightCB.lHeight = vih->bmiHeader.biHeight;
		hr = m_pGrabber->SetCallback(&mRightCB, 1);
	}
	hr = m_pGrabber->SetBufferSamples(FALSE);
	hr = m_pGrabber->SetOneShot(FALSE);

因为定义的对象的类是一样的 ,而且我们需要的我在这里是相当于将两个相机 的BufferCB回调函数 ,都使用了这一个, 那么当两个相机都有数据的时候是什么情况呢 …
结果是出现了两个相机的得到的图像混乱,数据丢失等情况 ,我检查了其他很多代码 ,感觉都是没问题 ,
最后 灵光一闪 ,我重新继承了ISampleGrabberCB类 ,又写了一个 和上面一模一样的类 ,就是类名不一样而已 ,这样就分别对两个相机 抓图的回调函数 分开了 .然后数据就正常了 ,
之后我是想过在一个类在重载一个BufferCB回调来着 .但是想了一下好像不行 ,他是一个虚函数 ,我多次重载还是分辨不出来
.算了 就这样
所以如果需要很多个相机 ,就要重写很多个*

ISampleGrabberCB

*类

我想不到别的办法 ,.如果有哪位有好的思路的 ,欢迎qq联系我 1975131393
如果没有思路的也可以参考我这个方法,也就是多复制几次而已

哈哈哈哈哈

//指定视频采集设备的友好名字,为它创建一个Filter IBaseFilter * CTestPreviewDlg::CreateVideoDevice(const char * inFriendlyName) { return CreateHardwareFilter(CLSID_VideoInputDeviceCategory,inFriendlyName); } //根据设备的友好名字,创建一个代表该设备的Filter IBaseFilter * CTestPreviewDlg::CreateHardwareFilter(GUID inCategory,const char * inFriendlyName) { //创建一个系统枚举组件对象 ICreateDevEnum * enumHardware = NULL; HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_ALL, IID_ICreateDevEnum,(void**)&enumHardware); if(FAILED(hr)) { return NULL; } IBaseFilter * hardwareFilter = NULL; IEnumMoniker * enumMoniker = NULL; //为指定的目录创建枚举器 hr = enumHardware->CreateClassEnumerator(inCategory,&enumMoniker,0); if(enumMoniker) { enumMoniker->Reset(); ULONG fetched = 0; IMoniker * moniker = NULL; char friendlyName[256]; //枚举得到该目录下所有的设备,逐个进行名字匹配 while(!hardwareFilter && SUCCEEDED(enumMoniker->Next(1,&moniker, &fetched)) && fetched) { if(moniker) { IPropertyBag * propertyBag = NULL; VARIANT name; friendlyName[0] = 0; hr = moniker->BindToStorage(0,0,IID_IPropertyBag,(void**)&propertyBag); //读取设备的友好名字 if(SUCCEEDED(hr)) { name.vt = VT_BSTR; hr = propertyBag->Read(L"Friendlyname",&name,NULL); } if(SUCCEEDED(hr)) { WideCharToMultiByte(CP_ACP,0,name.bstrVal,-1, friendlyName,256,NULL,NULL); //如果当前设备的友好名字与用户指定的设备名字相同, //则将当前设备标识绑定为Filter形式 if(strcmp(friendlyName,inFriendlyName) == 0) { moniker->BindToObject(0,0,IID_IBaseFilter, (void**)&hardwareFilter); } } //释放使用过的接口 if(propertyBag) { propertyBag->Release(); propertyBag = NULL; } moniker->Release(); } } enumMoniker->Release(); } enumHardware->Release(); return hardwareFilter; }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值