基本信息
源码名称:c++ 虚拟摄像头
源码大小:0.14M
文件格式:.zip
开发语言:C/C++
更新时间:2020-09-11
友情提示:(无需注册或充值,赞助后即可获取资源下载链接)
嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300
本次赞助数额为: 2 元×
微信扫码支付:2 元
×
请留下您的邮箱,我们将在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; }