Simultaneous Previewing & Video Capture using DirectShow
Introduction
This article explains a method to perform previewing and grabbing simultaneously from a Webcam using DirectShow. Rather than using the conventional ISampleGrabber interface, this application used Directshow VMR filters & IPin interfaces.
There are many solutions for capturing and previewing, but only a few combine both. I tried to make an application that serves this purpose by using the ISampleGrabber and IVideoWindow interfaces. In this this article, I will discuss the "VMR filters & IPin interfaces" method, which worked on Win2000 and WinXP.
The DirectShow "Windowless Sample" (Windowless mode in the Video Mixing Renderer) gives the clue for capturing frames while previewing.
Snap Shot
Using the Code
I had created a class named CVMR_Capture, and then inserted the VMR_Capture.h and VMR_Capture.cpp files into project.
Link strmiids.lib quartz.lib in VC++ Project Settings. Add a static control into your dialog resource. Add a member variable for that static control. Declare a member variable of CVMR_Capture.
Functions and Explanation
The public interfaces provided are:
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); (Optional)
Enumerate the available devices connected to the computer. HWND is the HANDLE to a combo box that displays the connected Devices.
HRESULT Init(int iDeviceID,HWND hWnd,int iWidth,int iHeight);
Intitializing, "iDeviceID" is the selected device index (from the combo box) and "hWnd" is the handle of the display window. iWidth and iHeight are the expected resolution (eg 320/240). The display will adjust iteself to the size of the window.
DWORD GrabFrame(); DWORD GetFrame(BYTE ** pFrame);
Call this function to get the captured buffer. GrabFrame(); will grab the image, store it in a buffer, and return the value that is the size of the buffer. The user can get the buffer pointer by calling GetFrame(BYTE ** pFrame), whichs return the size of the buffer.
Note: DONT DELETE the "pFrame" BUFFER VALUE, which the class destructor will delete. Use the Pointer(pFrame) for processing or copying the memory to a user-allocated Buffer.
BOOL StopVMR();
Stop previewing.
BOOL Pause();
Pause capturing. Call this method again to restart capturing.
DWORD ImageCapture(LPCTSTR szFile);
Capture and write the raw image BYTES (RGB) to a file provided.
Special Functions and Explanation
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);
Bind the filter to the given device ID.
HRESULT InitializeWindowlessVMR(HWND hWnd);
VMR intialization to the HWND provided.
HRESULT InitVideoWindow(HWND hWnd,int width, int height);
Adjusts the display video size according to the size of display window.
void StopCapture();
Stop capturing.
void CloseInterfaces(void);
Release & delete the interfaces/allocated memory.
void DeleteMediaType(AM_MEDIA_TYPE *pmt);
Delete media type object.
bool Convert24Image(BYTE *p32Img,BYTE *p24Img,DWORD dwSize32);
The captured image using VMR is a 32-bit RGB. This function will convert the 32-bit RGB to a 24-bit RGB.
Points of Interest
This class has been tested on Windows 2000 & Windows XP with DirectX9.0. Both VMR7 & VMR9 are supported. I haven't included the DirectShow Event Handling part in this sample. Please attach the required exception/error handling mechanism when you use it.
Please drop me an e-mail about any bugs or suggestions to enhance the class. Your suggestions and guidance will be most valuable.

Comments
WaitForCompletion ??
Posted by techratna on 08/03/2007 01:02pmDirectshow filter for 90 degree video rotation
Posted by nireshdev on 08/24/2006 01:15amHi, I tried your project it is working fine in my pc. I want to create a Directshow filter to create a 90 degree rotated video which is capturing from webcam. and i want to use that filter in Directshow grapedit, for that what should i do please help me. Thanks,
ReplyCan't display image using Logitech webcam
Posted by chewkokhooi on 06/26/2006 09:47pmimagecapture( )
Posted by sup_ho on 01/03/2006 09:35pmhi, i was trying to use your program, added a push button to capture the image, and found that it saves a file a corrupt file, the input for this function was "mog.bmp" was just wondering if it was cuz the bmpheader was not defined when i saved the file?
-
-
Replybitmap info
Posted by _mijo on 01/18/2006 02:03pmhi, i tried to capture an image using imagecapture() but i have the same problem with the saved file. what exactly do i have to define in order to get a good bitmap?
Replybitmap info and header
Posted by sup_ho on 01/03/2006 10:08pmyea.. theses info and headers weren't defined, that's what was cuzing the problem.. even thought they are defined in the showpic
ReplyConnecting a Decoder
Posted by Poorna on 09/17/2005 07:37amHi, I used your code to build my sample application. I am trying to use Encoder and decoder filters as follows Video Capture->H263 Encoder->H263 Decoder->Video Renderer. COnnect() for Encoder output and Decoder input pin fails. Please suggest me how to proceed.
ReplyBig Error
Posted by khkh on 07/28/2005 10:51amThis simple can't work with pinnacle AV/DV studio.
Replycompile error
Posted by shayirli on 06/14/2005 07:55amHello, I have a problem when I try to build this project as below: Please reply me about this problem: My mail: shayirli@yahoo.com or shayirli@aselsan.com.tr -------------------Configuration: DXCapture - Win32 Release-------------------- Compiling... DXCapture.cpp C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(2730) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(2736) : error C2061: syntax error : identifier 'HSEMAPHORE' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(2841) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(2856) : error C2061: syntax error : identifier 'HSEMAPHORE' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(15359) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(15542) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(15669) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(15674) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(16189) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(16203) : error C2061: syntax error : identifier 'HEVENT' DXCaptureDlg.cpp C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(2730) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(2736) : error C2061: syntax error : identifier 'HSEMAPHORE' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(2841) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(2856) : error C2061: syntax error : identifier 'HSEMAPHORE' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(15359) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(15542) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(15669) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(15674) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(16189) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(16203) : error C2061: syntax error : identifier 'HEVENT' VMR_Capture.cpp C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(2730) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(2736) : error C2061: syntax error : identifier 'HSEMAPHORE' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(2841) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(2856) : error C2061: syntax error : identifier 'HSEMAPHORE' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(15359) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(15542) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(15669) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(15674) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(16189) : error C2061: syntax error : identifier 'HEVENT' C:\DERS\TEZ\DIRECTX9\DIRECTX9.0C\INCLUDE\strmif.h(16203) : error C2061: syntax error : identifier 'HEVENT' Generating Code... Error executing cl.exe. DXCapture.exe - 30 error(s), 0 warning(s)
-
Replystrmif.h
Posted by shayirli on 06/15/2005 07:51amI think reason of this problem is DWORD_PTR, it is undefined for this code.Please help me, to define DWORD_PTR for this project.
ReplyRequesting specific image dimensions from Sample Grabber possible?
Posted by Walegwa on 04/06/2005 09:26pmSince you mention SampleGrabber, let me ask you this. Is it possible to ask the that filter for a 640 X 480 image, for example? I have a working bitmap grabber but I never know what size image I'm going to get. Some days it's 320 X 240, other days its 720 X 480, depending, I guess, on what side of the bed my camera woke up on. I haven't looked at your code yet so I apologize if the answer is in there.
-
-
Replyhow to process live image
Posted by aden003 on 04/04/2006 05:17ami wan to ask how to process the RGB from the live image and where the buffer
ReplyRe: Requesting specific image dimensions
Posted by Buddie on 05/06/2005 05:24pmyes we can a specific dimension .. HRESULT Init(int iDeviceID,HWND hWnd,int iWidth,int iHeight); Intitializing, "iDeviceID" is the selected device index (from the combo box) and "hWnd" is the handle of the display window. iWidth and iHeight are the expected resolution OFFERED BY THE CAMERA(eg 320/240). The display will adjust iteself to the size of the window. Sorry ..I have been busy of late
ReplyPlease help me on Directshow +MFC
Posted by nvnoi76 on 12/01/2004 09:41pmHi, I write a program to play Video files using Directshow and MFC ( Visual C++ 6.0 , DirectX 9.0 ) I compile in DEBUG mode, It runs well and correctly. But when I compile in RELEASE mode. It reports error : "Unhandle exception in Playwnd.exe (MFC42.dll)0xC0000005: Access Violation" Is there any problem on MFC42.dll ? Please help me to correct it. Thank you very much. Noi - nvnoi76@yahoo.com
Reply