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

【核心代码】
#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; }
好例子网口号:伸出你的我的手 — 分享!
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论