在好例子网,分享、交流、成长!
您当前所在位置:首页C/C++ 开发实例桌面应用界面/GUI → c++ 虚拟摄像头

c++ 虚拟摄像头

桌面应用界面/GUI

下载此实例
  • 开发语言:C/C++
  • 实例大小:0.14M
  • 下载次数:59
  • 浏览次数:637
  • 发布时间:2020-09-11
  • 实例类别:桌面应用界面/GUI
  • 发 布 人:jamryhlz
  • 文件格式:.zip
  • 所需积分:2
 相关标签: 摄像头 摄像

实例介绍

【实例简介】虚拟摄像头
【实例截图】

【核心代码】


#include <Windows.h>
#include <stdio.h>

#include "vcam_dshow.h"
#include "vcamera.h"
#include <atlbase.h>

///
static LONG LockCount = 0 ; ////
/////

VCamDShow::VCamDShow(IUnknown* pUnk, REFCLSID clsid, FRAME_CALLBACK cbk, void* param):
	m_pUnk(pUnk? pUnk : ((IUnknown*)static_cast<INonDelegatingUnknown*>(this)) ),
	m_clsid(clsid), m_callback(cbk), m_param(param)
{
	m_RefCount = 0;
	InitializeCriticalSection(&m_cs);
	m_State = State_Stopped;
	m_tStart = 0;
	m_pGraph = NULL;
	m_pName = NULL;
	m_pSink = NULL;
	m_pClock = NULL;

	////
	m_Stream = new VCamStream(this);
	m_AllPins[0] = m_Stream;
	m_AllPinsCount = 1; ///只有一个output
	/////
	InterlockedIncrement(&LockCount);
}
VCamDShow::~VCamDShow()
{
	SAFE_RELEASE(m_pClock);
	if (m_pName)free(m_pName);

	////
	delete m_Stream;

	///
	::DeleteCriticalSection(&m_cs);

	////
	InterlockedDecrement(&LockCount);
	printf("VCamDShow::~VCamDShow()");
//	MessageBox(0, "VCamDShow::~VCamDShow()", 0, 0);
}
#pragma comment(lib,"rpcrt4.lib")
HRESULT STDMETHODCALLTYPE VCamDShow::NonDelegatingQueryInterface(
	REFIID riid,
	__RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject)
{
	HRESULT hr = S_OK;
	if (!ppvObject)return E_POINTER;
	*ppvObject = NULL;
	///
	if (riid == IID_IAMStreamConfig || riid == IID_IKsPropertySet) {
	    ///
		return m_Stream->QueryInterface(riid, ppvObject);
	}

	/////
	if (riid == IID_IUnknown) {
		*ppvObject = static_cast<INonDelegatingUnknown*>(this);
	}
	else if ( riid == IID_IBaseFilter) {
		*ppvObject = static_cast<IBaseFilter*>(this);
	}
	else if (riid == IID_IPersist) {
		*ppvObject = (IPersist*)this;
	}
	else if (riid == IID_IMediaFilter) {
		*ppvObject = (IMediaFilter*)this;
	}
	else if (riid == IID_IAMovieSetup) {
		*ppvObject = (IAMovieSetup*)this;
	}
	else {
		*ppvObject = 0;
		printf("VCamDShow :QI No Interface.\n");
		///
		hr = E_NOINTERFACE;
	}

	////
	if (hr == S_OK) {
		
		AddRef();
	}

	return hr;
}
ULONG STDMETHODCALLTYPE VCamDShow::NonDelegatingAddRef(void)
{
	return InterlockedIncrement(&m_RefCount);
}
ULONG STDMETHODCALLTYPE VCamDShow::NonDelegatingRelease(void)
{
	LONG cnt = InterlockedDecrement(&m_RefCount);
	if (cnt == 0) {
		delete this;
	}
	return cnt;
}

HRESULT STDMETHODCALLTYPE VCamDShow::GetClassID(
	__RPC__out CLSID *pClassID)
{
	if (!pClassID)return E_POINTER;
	*pClassID = m_clsid; 
	return S_OK;
}


DWORD CALLBACK VCamDShow::helper_thread(void* p)
{
	struct S { VCamDShow* pthis;  FILTER_STATE state; };
	S* s = (S*)p;
	////
	Sleep(10);
	////
	s->pthis->m_State = s->state;

	delete s;
	////
	return 0;
}
void VCamDShow::setState(FILTER_STATE state)
{
	struct S { VCamDShow* pthis;  FILTER_STATE state; };
	S* s = new S;
	s->pthis = this;
	s->state = state;
	DWORD tid; 
	CloseHandle(CreateThread(NULL, 0, helper_thread, s, 0, &tid));
	////
}

HRESULT STDMETHODCALLTYPE VCamDShow::Stop(void)
{
	CLock lck(m_cs);
	HRESULT hr = S_OK;  ///
	if (m_State != State_Stopped) {
		////
		if (m_Stream->m_ConnectedPin) {
			m_Stream->Active(FALSE);
		}
	}
	////
	setState(State_Stopped); //
	
	///
	return hr;
}


HRESULT STDMETHODCALLTYPE VCamDShow::Pause(void)
{
	////
	CLock lck(m_cs);
	HRESULT hr = S_OK;
	if (m_State == State_Stopped) {
		if (m_Stream->m_ConnectedPin) {
			hr=m_Stream->Active(TRUE);
		}
	}
	setState(State_Paused); // 
	
	return hr;
}

HRESULT STDMETHODCALLTYPE VCamDShow::Run(REFERENCE_TIME tStart)
{
	CLock lck(m_cs); 
	///
	Sleep(500); ///
	////
	HRESULT hr = S_OK;//
	if (m_State == State_Stopped) {
		hr = Pause();
		if (FAILED(hr))return hr;
	}
	if (m_State != State_Running) {
		///
	}
	////
	m_tStart = tStart; ///
	setState(State_Running);

	return hr;
}

HRESULT STDMETHODCALLTYPE VCamDShow::SetSyncSource(
	__in_opt  IReferenceClock *pClock)
{
	////
	CLock lck(m_cs);
	SAFE_RELEASE(m_pClock); //
	m_pClock = pClock;
	if(m_pClock)
		m_pClock->AddRef();
	///
	return S_OK;
}
HRESULT STDMETHODCALLTYPE VCamDShow::GetSyncSource(
	__deref_out_opt  IReferenceClock **pClock)
{
	if (!pClock)return E_POINTER;

	CLock lck(m_cs);

	if (m_pClock)m_pClock->AddRef();
	*pClock = m_pClock;
	return S_OK;
}

HRESULT VCamDShow::getStreamTime(REFERENCE_TIME& now)
{
	HRESULT hr = S_OK;
	CLock lck(m_cs);
	if (m_pClock == NULL) {
		return VFW_E_NO_CLOCK;
	}
	hr = m_pClock->GetTime(&now);
	if (SUCCEEDED(hr)) {
		now -= m_tStart;
	}
	///
	return hr;
}

/// ENUM
class CEnumPins : public IEnumPins
{
protected:
	LONG m_RefCount;
	LONG m_Position;

	VCamDShow* m_Filter;

public:
	CEnumPins(VCamDShow* vcam, CEnumPins* o):m_Filter(vcam), m_Position(0), m_RefCount(1){
		m_Filter->AddRef();
		if (o) m_Position = o->m_Position;
	}
	~CEnumPins() {
		m_Filter->Release();
	}
public:
	virtual HRESULT STDMETHODCALLTYPE QueryInterface(
		REFIID riid,
		__RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject) {
		HRESULT hr = S_OK;
		if (!ppvObject)return E_POINTER;
		if (riid == IID_IUnknown || riid == IID_IEnumPins) {
			*ppvObject = (IEnumPins*)(this);
		}
		else {
			*ppvObject = 0;
			printf("VCamDShow :QI No Interface.\n");
			///
			hr = E_NOINTERFACE;
		}
		////
		if (hr == S_OK) {
			AddRef();
		}

		return hr;
	}
	virtual ULONG STDMETHODCALLTYPE AddRef(void) {
		return InterlockedIncrement(&m_RefCount);
	}
	virtual ULONG STDMETHODCALLTYPE Release(void) {
		LONG cnt = InterlockedDecrement(&m_RefCount);
		if (cnt == 0) {
			delete this;
		}
		return cnt;
	}
	//////
	STDMETHODIMP Next(
		ULONG cPins,         // place this many pins...
		__out_ecount(cPins) IPin ** ppPins,    // ...in this array of IPin*
		__out_opt ULONG * pcFetched    // actual count passed returned here
	) 
	{
		HRESULT hr = S_OK;
		if (pcFetched != NULL) {
			*pcFetched = 0;           // default unless we succeed
		}
		else if (cPins>1) {     // pcFetched == NULL
			return E_INVALIDARG;
		}
		ULONG cFetched = 0;

		while (cPins) {
			//
			if (m_Position >= m_Filter->m_AllPinsCount)break;
			*ppPins = m_Filter->m_AllPins[m_Position  ];
			if (!*ppPins)break;
			(*ppPins)->AddRef();

			////
			ppPins  ;
			cFetched  ;
			cPins--;
		}
		if (pcFetched != NULL) {
			*pcFetched = cFetched;
		}

		return (cPins == 0 ? NOERROR : S_FALSE);
	}

	STDMETHODIMP Skip(ULONG cPins) {
		if (cPins == 0)return S_OK;
		m_Position  = cPins;
		if (m_Position >= m_Filter->m_AllPinsCount) return E_UNEXPECTED;
		return S_OK;
	}
	STDMETHODIMP Reset() { m_Position = 0; return S_OK; }
	STDMETHODIMP Clone(__deref_out IEnumPins **ppEnum) {
		HRESULT hr = S_OK;
		if (!ppEnum)return E_POINTER;

		*ppEnum = new CEnumPins(m_Filter, this);
		if (!*ppEnum)return E_OUTOFMEMORY;
		return hr;
	}
};

HRESULT STDMETHODCALLTYPE VCamDShow::EnumPins(
	__out  IEnumPins **ppEnum)
{
	if (!ppEnum)return E_POINTER;

	*ppEnum = new CEnumPins(this, NULL); 
	if (!*ppEnum)return E_OUTOFMEMORY;
	return S_OK;
}

HRESULT STDMETHODCALLTYPE VCamDShow::FindPin(
	LPCWSTR Id,
	__out  IPin **ppPin)
{ 
	if (!Id || !ppPin) { return E_POINTER; }  
	////
	for (int i = 0; i < m_AllPinsCount;   i) {
		if (wcscmp(m_AllPins[i]->m_PinName, Id) == 0) {
			*ppPin = m_AllPins[i];
			(*ppPin)->AddRef();
			return S_OK;
		}
	}
	*ppPin = NULL;
	return VFW_E_NOT_FOUND;
}
HRESULT STDMETHODCALLTYPE VCamDShow::QueryFilterInfo(
	__out  FILTER_INFO *pInfo)
{
	if (!pInfo)return E_POINTER; 
	CLock lck(m_cs);
	if (m_pName) {
		wcscpy(pInfo->achName, m_pName);
	}
	else {
		pInfo->achName[0] = 0;
	}
	pInfo->pGraph = m_pGraph;
	if (pInfo->pGraph)pInfo->pGraph->AddRef();
	////
	return S_OK;
}

HRESULT STDMETHODCALLTYPE VCamDShow::JoinFilterGraph(
	__in_opt  IFilterGraph *pGraph,
	__in_opt  LPCWSTR pName)
{
	CLock lck(m_cs); 
	///
	m_pSink = NULL;
	m_pGraph = pGraph;
	if (m_pGraph) {
		m_pGraph->QueryInterface(IID_IMediaEventSink,
			(void**)&m_pSink);
		///
		if (m_pSink)m_pSink->Release();
		///
	}
	/////
	if (m_pName) {
		free(m_pName);
		m_pName = NULL;
	}
	if (pName) {
		m_pName = (wchar_t*)malloc(sizeof(wchar_t)*(wcslen(pName)   1) );
		wcscpy(m_pName, pName);
	}
	return S_OK;
}
HRESULT VCamDShow::NotifyEvent(long EventCode,
	LONG_PTR EventParam1,LONG_PTR EventParam2)
{
	CLock lck(m_cs);
	// Snapshot so we don't have to lock up
	IMediaEventSink *pSink = m_pSink;
	if (pSink) {
		if (EC_COMPLETE == EventCode) {
			EventParam2 = (LONG_PTR)(IBaseFilter*)this;
		}

		return pSink->Notify(EventCode, EventParam1, EventParam2);
	}
	else {
		return E_NOTIMPL;
	}
}

////
HRESULT STDMETHODCALLTYPE VCamDShow::Register(void)
{
	printf("VCamDShow::Register(void) \n");
	//MessageBox(0, "VCamDShow::Register", 0, 0);
	return S_FALSE;

}
HRESULT STDMETHODCALLTYPE VCamDShow::Unregister(void)
{
	printf("VCamDShow::Unregister(void) \n");
	//MessageBox(0, "VCamDShow::Unregister", 0, 0);
	return S_FALSE;
}


////// Factory

class VCamDShowFactory : public IClassFactory
{
protected:
	LONG m_RefCount;

public:
	FRAME_CALLBACK m_callback;
	void* param; 

public:
	VCamDShowFactory() {
		m_RefCount = 0; ///
		///
		InterlockedIncrement(&LockCount);
	}
	~VCamDShowFactory() {
		InterlockedDecrement(&LockCount);
	}

public:
	
	STDMETHOD(QueryInterface)(REFIID iid, LPVOID* ppv) {
		if (!ppv) return E_POINTER;
		printf("Fact QI.\n");
		*ppv = 0;
		if (iid == IID_IUnknown || iid == IID_IClassFactory) {
			*ppv = static_cast<IClassFactory*>(this);
			AddRef();
			return S_OK;
		}
		return E_NOINTERFACE;
	}
	STDMETHOD_(ULONG, AddRef)() {

		return InterlockedIncrement(&m_RefCount);
	}
	STDMETHOD_(ULONG, Release)() {
		LONG cnt = InterlockedDecrement(&m_RefCount);
		if (cnt == 0) {
			delete this;
		}
		return cnt;
	}
	STDMETHOD(LockServer)(BOOL fLock) {
		if (fLock)InterlockedIncrement(&LockCount);
		else InterlockedDecrement(&LockCount);
		return S_OK;
	}
	STDMETHOD(CreateInstance)(IUnknown* pUnk, REFIID riid, LPVOID* ppv) {
		if (!ppv) return E_POINTER;
		
		/////
		VCamDShow* t = new VCamDShow(pUnk, CLSID_VCamDShow, m_callback, param);
		if (FAILED(t->QueryInterface(riid, ppv))) {
			delete t;
			return E_NOINTERFACE;
		}

		return S_OK;
	}
	
};

/////

REGPINTYPES PinTypes = {
	&MEDIATYPE_Video,
	&MEDIASUBTYPE_NULL
};
REGFILTERPINS VCamPins = {
	L"Pins",
	FALSE, /// 
	TRUE,  /// output
	FALSE, /// can hav none
	FALSE, /// can have many
	&CLSID_NULL, // obs
	L"PIN",
	1,
	&PinTypes
};

static HRESULT RegisterVCamDShow(const char* file, BOOL bReg, BOOL bInProcServer )
{
	LPOLESTR pp;
	::StringFromIID(CLSID_VCamDShow , &pp);
	char pt[120];
	WideCharToMultiByte(CP_ACP, 0, pp, -1, pt, sizeof(pt), NULL, NULL);
	::CoTaskMemFree(pp);
	////
	char p[256]; strcpy(p, "CLSID\\"); strcat(p, pt);
	CRegKey key;
	if (key.Create(HKEY_CLASSES_ROOT, p) != 0) {
		printf("Not Open [%s]\n", p);
		return REGDB_E_CLASSNOTREG;
	}

	LONG status = 0;
	if (bReg) {
		if (bInProcServer) {
			status = key.SetKeyValue("InprocServer32", file);
			key.SetKeyValue("InprocServer32", "Both", "ThreadingModel");
		}
		else {
			status = key.SetKeyValue("LocalServer32", file);
			key.SetKeyValue("LocalServer32", "Both", "ThreadingModel");
		}
		printf(" KKK [%s] status=%d\n", p, status);
		//
	}
	else {
		key.DeleteSubKey("InprocServer32");
		key.DeleteSubKey("LocalServer32");
		strcpy(p, "CLSID");
		if (key.Create(HKEY_CLASSES_ROOT, p) != 0)
			return REGDB_E_CLASSNOTREG;
		key.DeleteSubKey(pt);
	}
	/////
	if (status == 0) {
		IFilterMapper2* pFM = NULL;
		HRESULT hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, IID_IFilterMapper2, (void**)&pFM);
		if (SUCCEEDED(hr)) {
			////
			IMoniker *pMoniker = 0;
			REGFILTER2 rf2;
			rf2.dwVersion = 1;
			rf2.dwMerit = MERIT_DO_NOT_USE;
			rf2.cPins = 1;
			rf2.rgPins = &VCamPins;

			if (bReg) {
				hr = pFM->RegisterFilter(CLSID_VCamDShow, L"Fanxiushu DShow VCamera", &pMoniker, &CLSID_VideoInputDeviceCategory, NULL, &rf2);
			}
			else {
				hr = pFM->UnregisterFilter( &CLSID_VideoInputDeviceCategory, NULL, CLSID_VCamDShow);
			}
			if (FAILED(hr)) {
				printf("FilterMapper2  RegisterFilter or UnregisterFilter err=0x%X\n", hr );
				status = hr;
			}
			/////

			pFM->Release();
		}
		else {
			status = hr;
			printf("CoCreateInstance IFilterMapper2 err=0x%X\n", hr );
		}
	}
	else {
		status = REGDB_E_CLASSNOTREG;
		printf("Change Registery Err status=0x%X\n", status );
	}
	
	return status;
}

/////DLL Export

STDAPI DllCanUnloadNow(void)
{
	///
	if (LockCount == 0)return S_OK;
	else return S_FALSE;
}

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
	if (!ppv)return E_POINTER;
	*ppv = 0;
	if (rclsid != CLSID_VCamDShow) {
		return E_NOINTERFACE;
	}
	if (!(riid == IID_IUnknown) && !(riid == IID_IClassFactory)) {
		return E_NOINTERFACE;
	}

	////
	VCamDShowFactory* fact = new VCamDShowFactory;
	fact->m_callback = VCam_Frame_Callback;        // 获取视频帧数据
	fact->param = 0;

	HRESULT hr = fact->QueryInterface(riid, ppv);
	if (FAILED(hr)) {
	   //
		delete fact;
	}
	
	return hr;
}

STDAPI DllRegisterServer()
{
	char path[MAX_PATH];
	GetModuleFileName(g_hInstance, path, MAX_PATH);
	HRESULT hr = RegisterVCamDShow(path, TRUE, TRUE);
	return hr;
}

STDAPI DllUnregisterServer()
{
	HRESULT hr = RegisterVCamDShow(NULL, FALSE, TRUE);
	return hr;
}


标签: 摄像头 摄像

实例下载地址

c++ 虚拟摄像头

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警