使用 DirectShow 进行同步预览和视频捕获
一种使用 DirectShow 从网络摄像头同时进行预览和帧捕获的方法。
引言
本文介绍了一种使用 DirectShow 从网络摄像头同时执行预览和抓取的方法。除了使用传统的 ISampleGrabber
接口外,此应用程序还使用 DirectShow VMR 过滤器和 IPin 接口。
背景
有很多用于捕获和预览的解决方案,但很少有将两者结合起来的。我尝试使用 ISampleGrabber
和 IVideoWindow
接口创建一个实现此目的的应用程序。它在 Windows 2000 上运行良好,但在 XP 上表现不佳。
DirectShow "无窗口示例"(视频混合渲染器中的无窗口模式)为在预览时捕获帧提供了线索。
使用代码
我创建了一个名为 CVMR_Capture
的类。要使用此类
- 将 VMR_Capture.h 和 VMR_Capture.cpp 文件插入到您的项目中。
- 在 VC++ 项目设置中链接 strmiids.lib、quartz.lib。
- 在您的对话框资源中添加一个静态控件。
- 为该静态控件添加一个成员变量。
- 声明
CVMR_Capture
的成员变量。
提供的公共接口是
int EnumDevices(HWND hList); HRESULT Init(int iDeviceID,HWND hWnd,int iWidth,int iHeight); DWORD GetFrame(BYTE ** pFrame); BOOL StopVMR(); BOOL Pause(); DWORD ImageCapture(LPCTSTR szFile); DWORD GrabFrame();
-
int EnumDevices(HWND hList);(可选)
枚举连接到计算机的可用设备。
HWND
是显示连接设备的组合框的句柄。 -
HRESULT Init(int iDeviceID,HWND hWnd,int iWidth,int iHeight);
初始化。
iDeviceID
是选定的设备索引(来自组合框),hWnd
是显示窗口的句柄,iWidth
和iHeight
是预期的分辨率(例如:320/240)。显示将自身调整为窗口的大小。 -
DWORD GrabFrame();
-
DWORD GetFrame(BYTE ** pFrame);
调用这些函数以获取捕获的缓冲区。
GrabFrame();
将抓取图像。将其存储在缓冲区中,返回值是缓冲区的大小。用户可以通过调用GetFrame(BYTE ** pFrame)
来获取缓冲区指针,该指针返回缓冲区的大小。不要删除 "pFrame" 缓冲区值,它将由类析构函数删除。使用指针(pFrame)用于处理或将内存复制到用户分配的缓冲区。
-
BOOL StopVMR();
停止预览。
-
BOOL Pause();
暂停捕获。再次调用此方法以重新开始捕获。
-
DWORD ImageCapture(LPCTSTR szFile);
捕获并将原始图像字节 (RGB) 写入提供的文件。
特殊函数和说明
bool BindFilter(int deviceId, IBaseFilter **pFilter); HRESULT InitializeWindowlessVMR(HWND hWnd); HRESULT InitVideoWindow(HWND hWnd,int width, int height); void StopCapture(); void CloseInterfaces(void); void DeleteMediaType(AM_MEDIA_TYPE *pmt); bool Convert24Image(BYTE *p32Img,BYTE *p24Img,DWORD dwSize32);
-
bool BindFilter(int deviceId, IBaseFilter **pFilter);
将过滤器绑定到给定的设备 ID。
-
HRESULT InitializeWindowlessVMR(HWND hWnd);
将 VMR 初始化为提供的
HWND
。 -
HRESULT InitVideoWindow(HWND hWnd,int width, int height);
根据显示窗口的大小调整显示视频大小。
-
void StopCapture();
停止捕获。
-
void CloseInterfaces(void);
释放并删除接口/分配的内存。
-
void DeleteMediaType(AM_MEDIA_TYPE *pmt);
删除媒体类型对象。
-
bool Convert24Image(BYTE *p32Img,BYTE *p24Img,DWORD dwSize32);
使用 VMR 捕获的图像是 32 位 RGB。此函数将 32 位 RGB 转换为 24 位 RGB。
关注点
此类在 Windows 2000 和 Windows XP 上使用 DirectX9.0 进行了测试。支持 VMR7 和 VMR9。我没有在此示例中包含 DirectShow 事件处理部分。使用时请附加所需的异常/错误处理机制。
请给我发送电子邮件,告诉我任何错误或改进该类的建议。您的建议和指导将最有价值。