|
9.3.3 视频图像捕获类CVMR_Capture的实现(1)
为完成采集视频、预览视频和捕获图像帧的任务,我们封装了CVMR_Capture类,使用VMR技术流畅显示和捕捉图像帧。根据GraphEdit的滤波器内容和链表的操作,编程(www.cppentry.com)实现使用VMR技术显示、捕捉图像。
类CVMR_Capture定义在头文件VMR_Capture.h中。
enum PLAYER_STATE {INIT,RUNNING,PAUSED,STOPPED}; class CVMR_Capture { public: CVMR_Capture(); //类构造器 virtual ~CVMR_Capture(); //类析构器 int EnumDevices(HWND hList); //枚举设备 HRESULT Init(int iDeviceID,HWND hWnd,int iWidth,int iHeight); //根据设备索引号初始化 DWORD GetFrame(BYTE ** pFrame); //获取捕获的图像帧 BOOL Pause(); //暂停预览、捕获 DWORD GrabFrame(); //截获图像 void CloseInterfaces(void); //关闭接口,释放资源 void SaveGraph(CString wFileName); //保存滤波器链表 protected: IGraphBuilder *m_pGB; //滤波器链表管理器 IMediaControl *m_pMC; //媒体控制接口 IMediaEventEx *m_pME; //媒体事件接口 IVMRWindowlessControl9 *m_pWC; //VMR-9接口 IPin *m_pCamOutPin; //视频采集滤波器引脚 IBaseFilter *m_pDF; //视频采集滤波器 PLAYER_STATE m_psCurrent; int m_nWidth; //图像帧宽度 int m_nHeight; //图像帧高度 BYTE *m_pFrame; //捕获的图像帧数据指针 long m_nFramelen; //捕获的图像帧数据大小 bool BindFilter(int deviceId, IBaseFilter **pFilter); //设备与滤波器捆绑 HRESULT InitializeWindowlessVMR(HWND hWnd); //初始化无窗口模式的VMR HRESULT InitVideoWindow(HWND hWnd,int width, int height); //初始化视频窗口 void StopCapture(); void DeleteMediaType(AM_MEDIA_TYPE *pmt); //删除媒体类型 bool Convert24Image(BYTE *p32Img,BYTE *p24Img,DWORD dwSize32); //颜色空间转换 private: }; |
CVMR_Capture类封装了使用VMR技术的成员函数和成员变量,包括类的构造器、析构器,滤波器链表管理器接口、媒体控制接口、媒体事件接口,图像帧的宽度、高度及操作VMR的保护成员函数等。
类CVMR_Capture有关初始化、析构等,类实现VMR_Capture.cpp文件中。
//释放资源的宏 #define RELEASE_POINTER (x) { if (x) x->Release(); x = NULL; } /*类构造器*/ CVMR_Capture::CVMR_Capture() { CoInitialize(NULL); //初始化COM库 //接口指针清空 m_pGB = NULL; m_pMC = NULL; m_pME = NULL; m_pWC = NULL; m_pDF =NULL; m_pCamOutPin =NULL; m_pFrame=NULL; m_nFramelen=0; m_psCurrent=STOPPED; } /*类析构器*/ CVMR_Capture::~CVMR_Capture() { CloseInterfaces(); //清空指针、释放资源 CoUninitialize( ); //卸载COM库 } /*释放所有资源,断开链接*/ void CVMR_Capture::CloseInterfaces(void) { HRESULT hr; //停止媒体回放 if(m_pMC) hr = m_pMC->Stop(); m_psCurrent = STOPPED; //释放并清零接口指针 if(m_pCamOutPin) m_pCamOutPin->Disconnect(); //断开引脚的链接 RELEASE_POINTER(m_pCamOutPin); //视频采集滤波器引脚清空 RELEASE_POINTER(m_pMC); //媒体控制接口清空 RELEASE_POINTER(m_pGB); //滤波器链表管理器接口清空 RELEASE_POINTER(m_pWC); //VMR-9接口清空 RELEASE_POINTER(m_pDF); //视频采集滤波器接口清空 //释放分配的内存 if(m_pFrame!=NULL) delete []m_pFrame; //释放图像空间缓存 }
|
上述程序完成资源释放、指针清空等工作,在退出应用程序时调用此函数。
枚举本地系统的采集设备。
/* 枚举本地系统的采集设备*/ int CVMR_Capture::EnumDevices(HWND hList) { if (!hList) return -1; int id = 0; //枚举所有视频采集设备 ICreateDevEnum *pCreateDevEnum; //生成设备枚举器 HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pCreateDevEnum); if (hr != NOERROR) return -1; IEnumMoniker *pEm; //创建视频类枚举器 hr = pCreateDevEnum->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &pEm, 0); if (hr != NOERROR) return -1; pEm->Reset(); //复位设备 ULONG cFetched; IMoniker *pM; while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK) //根据索引获取设备 { IPropertyBag *pBag; //获取属性集 hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag); if(SUCCEEDED(hr)) { VARIANT var; var.vt = VT_BSTR; //保存二进制数据 hr = pBag->Read(L"FriendlyName", &var, NULL); //以FriendlyName获取设备信息 if (hr == NOERROR) { id++; //把该设备的信息添加到组合框 (long)SendMessage(hList, CB_ADDSTRING, 0,(LPARAM)var. bstrVal); SysFreeString(var.bstrVal); //释放资源 } pBag->Release(); //释放资源 } pM->Release(); //释放资源 } return id; } |
|