Click here to Skip to main content
Click here to Skip to main content

Extracting bitmaps from movies using DirectShow

By , 4 Sep 2001
 
<!-- Download Links -->

Sample Image - FrameGrabberDemo.gif

Introduction

This article explains how to use the ISampleGrabber interface to grab a frame from a movie. We'll add the SampleGrabber filter to the graphbuilders filter list and use it to extract the bitmap. It'll show the necessary steps how to create the filter, create the graph, start it upp and grab the frame.

Setup the enviroment, we are using ATL smartpointers and DirectShow

#include "AtlBase.h"	// For atl smart pointers
#include "dShow.h"	// DirectShow header
#include "Qedit.h"	// SampleGrabber filter

The project has to be linked with Strmbase.lib

Since we're using COM we have to call CoInitialize() and CoUninitialize() in InitInstance, make sure the dialog destructor is called before CoUninitialize is called.

BOOL CFrameGrabberApp::InitInstance()
{
...
...
	CoInitialize(NULL);
	{
		CFrameGrabberDemoDlg dlg;
		m_pMainWnd = &dlg;
		int nResponse = dlg.DoModal();
	}
	CoUninitialize();
...
...
}

Step 1: Create the GraphBuilder

CComPtr<IGraphBuilder> pGraphBuilder;
HRESULT hr = ::CoCreateInstance(CLSID_FilterGraph, NULL, 
              CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void**)&pGraphBuilder);

Step 2: Create the Grabber filter and add it to the graph builder

CComPtr<IBaseFilter> pGrabberBaseFilter;
CComPtr<ISampleGrabber> pSampleGrabber;
AM_MEDIA_TYPE mt;
hr = ::CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
                        IID_IBaseFilter, (LPVOID *)&pGrabberBaseFilter);
if (FAILED(hr))
	return hr;
pGrabberBaseFilter->QueryInterface(IID_ISampleGrabber, (void**)&pSampleGrabber);
if (pSampleGrabber == NULL)
	return E_NOINTERFACE;
hr = pGraphBuilder->AddFilter(pGrabberBaseFilter,L"Grabber");
if (FAILED(hr))
	return hr;

Step 3: Setup the media type we're interrested in and render the file. The graph builder will now setup all the filters it needs to render the movie including the sample grabber we added.

ZeroMemory(&mt,sizeof(AM_MEDIA_TYPE));
mt.majortype = MEDIATYPE_Video;
mt.subtype = MEDIASUBTYPE_RGB24;
mt.formattype = FORMAT_VideoInfo; 
hr = pSampleGrabber->SetMediaType(&mt);
if (FAILED(hr)) 
	return hr;
hr = pGraphBuilder->RenderFile(wFile,NULL); 
if (FAILED(hr)) 
	return hr;

Now when the graph is created we need to tell the sample grabber to stop the graph after receiving one sample, we also tell it to copy the sample data into it's internal buffer.

hr = pSampleGrabber->SetBufferSamples(TRUE);
if (FAILED(hr)) 
	return hr; 
hr = pSampleGrabber->SetOneShot(TRUE); 
if (FAILED(hr)) 
return hr;

Step 4: Now we run the graph and collects the data from the sample grabber.

hr = pMediaControl->Run();
if (FAILED(hr)) 
	return hr; 
long evCode;
hr = pMediaEventEx->WaitForCompletion(INFINITE, &evCode); 
if (FAILED(hr)) 
	return hr; 
AM_MEDIA_TYPE MediaType; 
ZeroMemory(&MediaType,sizeof(MediaType)); 
hr = pSampleGrabber->GetConnectedMediaType(&MediaType); 
if (FAILED(hr)) 
	return hr; 
// Get a pointer to the video header. 
VIDEOINFOHEADER *pVideoHeader = (VIDEOINFOHEADER*)MediaType.pbFormat; 
if (pVideoHeader == NULL) 
	return E_FAIL; 
// The video header contains the bitmap information. 
// Copy it into a BITMAPINFO structure. 
BITMAPINFO BitmapInfo; 
ZeroMemory(&BitmapInfo, sizeof(BitmapInfo)); 
CopyMemory(&BitmapInfo.bmiHeader, &(pVideoHeader->bmiHeader), 
           sizeof(BITMAPINFOHEADER)); 

// Create a DIB from the bitmap header, and get a pointer to the buffer. 
void *buffer = NULL; 
HBITMAP hBitmap = ::CreateDIBSection(0, &BitmapInfo, DIB_RGB_COLORS, &buffer, 
                                     NULL, 0); 
GdiFlush(); 
// Copy the image into the buffer. 
long size = 0; 
hr = pSampleGrabber->GetCurrentBuffer(&size,(long *)buffer);   
if (FAILED(hr)) 
	return  hr;

Now we have the bitmap handle, the demo program takes the sample one second in the movie and displays it to the user using an picture box.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questionselect output device Pinmemberkinani11-Aug-11 6:32 
im using directshow to play wav and mp3 files but i want to be able to choose the output device before playing sound Any idea plz its urgent
GeneralThank youmemberXiaohu Shao26-Jul-10 17:08 
Hi,
It's a perfect article, it help me a lot learn the directshow.Thank you very much! Smile | :)
Xiaohu Shao
Generalerror C2504: 'IDXEffect' and error C2787: 'IVideoWindow' :memberVirex_A30-Oct-08 14:54 
This error is produced when I build the project.. How cn I fix this??
 
Im using VC++ 6.0 Windows XP OS, SDK 9
Generalcan't grub from the "*.mp4"memberlaguna_leo27-Sep-08 5:23 
in DirectX 9.0b, it returns after the codes run.
hr = pSampleGrabber->GetConnectedMediaType(&MediaType);
if (FAILED(hr))
return hr;
Generalto all - if doesn't run DX9membergrandmasta126-Aug-07 0:20 
change from:
hr = pGraphBuilder->RenderFile(wFile,NULL);
if (FAILED(hr))
return hr;
 
// QueryInterface for some basic interfaces
pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
pGraphBuilder->QueryInterface(IID_IMediaEvent, (void **)&pMediaEventEx);
 
if (pMediaControl == NULL || pMediaEventEx == NULL)
return E_NOINTERFACE;
 
change to:
 
// QueryInterface for some basic interfaces
pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
pGraphBuilder->QueryInterface(IID_IMediaEvent, (void **)&pMediaEventEx);
 
if (pMediaControl == NULL || pMediaEventEx == NULL)
return E_NOINTERFACE;
 
hr = pGraphBuilder->RenderFile(wFile,NULL);
if (FAILED(hr))
return hr;
QuestionUrgent Problem...memberTushar Jadhav22-Jun-07 19:22 
Hi,
I am working on a DirectShowEditing Service application. In that application I need to capture frame from the timeline. I used your code. I took GrapgBuilder pointer from the timeline using IRenderEngine. Then I procedded as per your code. The problem is that my application does not come out of the WaitForCompletion method of IMediaEvent. I dont know where the problem is. Can you pls help me in this matter.
 
Tushar
Generalimage won't fit to picturebox(CStatic)memberEd_lon17-May-07 20:49 
Hi, the code works perfectly fine. But a bigger picture won't resize to fit the picturebox.
Please help. thanks in advance!Smile | :)
 
Edd
Generalhimembervikram panwar26-Mar-07 23:54 
when i compile this code i got the two liking error
 
FrameGrabberDemoDlg.obj : error LNK2001: unresolved external symbol _IID_ISampleGrabber
 
FrameGrabberDemoDlg.obj : error LNK2001: unresolved external symbol _CLSID_SampleGrabber
plz tell wht i should do to resolve these errors

 
vikram panwar
GeneralRe: himemberrajendra@yahoo.com27-Mar-07 21:07 

link Strmiids.lib Strmbase.lib Winmm.lib Quartz.lib libs by using setting option.
GeneralIt Does not run in Win2kmemberrajendra@yahoo.com22-Mar-07 6:45 
Hi,
The application is not capturing first frame from movie file in win2k.
plz provide some information so that it can work in win2k.
 

QuestionThe other way aroundmembershfnet13-Mar-07 4:29 
Hello Markus,
I need to take a collection of jpegs or bitmaps, make a video out of it, and stream it to Windows Media Encoder. Is it possible to do it using DirectShow? Could you point me in the right direction?
Thanks,
shfnet D'Oh! | :doh:
AnswerRe: The other way aroundmembertanvon malik21-Nov-07 17:57 
Hi
Yes, but you have to create your own DirectShow source filter.
DirectShow source filter will convert the bmp jpeg in a video stream.
see my site for more info about DirectShow , DirectShow Filters, VC++.
 

Questionhow vedio file(mpeg4) is streamedmemberMember #248359415-Feb-07 18:38 
I also in a need of sending a vedio file(MPEG4) from server to client application.
that should play real time at client side .I am going to implement this by using C#.
but I don't know how to do that.
That mean how to divide the vedio(mpeg4) file into frames and send that frame to client in the server side and also how to play that in the client side.For that playing purpose I am going to use the directx.
 
Please please be kind enough to help me in any way
any sort of help is highly appreciated.
 
i am in a hurry please help me
 
thanks
madushan thilina
 
madushant@gmail.com Rose | [Rose]
madushant@yahoo.com
GeneralProblem opening file with bad indexesmemberSbarBaz29-Sep-06 6:07 
Hi, using this application I tryed opening an avi with bad indexes and I had a problem. If I play them using MPC I got not problems, when i use IGraphBuilder:RenderFile(), it can not build the graph.
Using Graph Edit, I noticed MPC uses different filters when it plays video with bad indexes, but that filters are not available in DirectShow, and using IGraphBuilder:RenderFile() the GraphBuilder can't find them.
Does someone know something about the filter used by MPC? Does it use internal filter? Is it possible using them? Can you play avi with bad indexes using directshow? If yes, what codec are you using? Is available source code for repairing an avi with bad indexes?
Please if you know something that can help me, or if you can redirect me to a better discussion place for this topic, reply... I'm very afraid with this problem. Thanks in advance for help.
GeneralConflict between directshow and wmplayer. Help!memberaritosteles10-Sep-06 12:13 
Hi.
I have a capture graph running (capturing video frames from a webcam)and if windows media player (or winamp) visualization is switched to full screen mode, my graph just seems to freeze. Nothing happens, no video, no errors, no events, nothing. When full screen mode is switched off everything goes back to normal.
Help anyone?
 
Thanks
Aritosteles
GeneralError when compilingmemberarindam_stcet3-May-06 4:19 
Hi All,
I got error while compiling this project.
The error is c:\program files\microsoft visual studio\vc98\include\strmif.h(1020) : error C2146: syntax error : missing ';' before identifier 'HSEMAPHORE'. I am using vc++ 6. I think there is a problem
with DWORD_PTR. Please anybody help me to solve this problem.
Thanking you
Regards
Arindam
 

 

GeneralError: Could not grab the frame.memberVenu Gopal Lolla13-Feb-06 19:09 
Hello,
 

I tried running the program on a small AVI file (1.29 MB) to grab a frame.
It gave an error "Could not grab the frame". The error is being generated
after a return at line 330 in FrameGrabberDemoDlg.cpp.
 
Could you suggest any possible reasons for failure.
Could you also send me an avi which you have tested successfully.
 
Thanks,
- Venu Lolla.
GeneralRe: Error: Could not grab the frame.memberbeatbox24-Mar-06 2:50 
Try doing this:
 
// Copy the image into the buffer.
long size = 0;
hr = pSampleGrabber->GetCurrentBuffer(&size, NULL); // **add this line to get size of buffer**
hr = pSampleGrabber->GetCurrentBuffer(&size, (long *)buffer);
 
Mike
QuestionTheoretical misunderstanding of a processmemberwhitesail6-Dec-05 13:25 
Imagine, camera is set to capture video stream 24fps with 1024x1280 pixel format. Also imagine that the picture which is grabbed appears to be static. I mean it doesn't change. How does one distinguish new frame from old one? That a cam has already physically changed the content taken from a ccd. (In case a cam works a bit slower) Is there any message ... or what is the way to synchronize the rates of physical refresh and nominated rate?
 
If I asked smth stupid, sorry, I'm new to all this.
GREG (kalenkov@mail.ru)
 
-- modified at 19:25 Tuesday 6th December, 2005
Generalcouldnt compilememberUsman mani16-Mar-05 22:50 
Following error were thr
 
FrameGrabberDemoDlg.obj : error LNK2001: unresolved external symbol _IID_ISampleGrabber
FrameGrabberDemoDlg.obj : error LNK2001: unresolved external symbol _CLSID_SampleGrabber
 
Usman
GeneralError saving the grabbed frame to bmp filememberA. Asif Raza15-Mar-05 10:38 
I used the given code in my application. The filter graph seems to be working fine and i dont get any error at compile or run time. To test whether the frame is grabbed successfuly or not I am using the following code to write the grabbed frame to a bmp file:
 

BOOL CMainDialog::WriteDIB(LPTSTR szFile, HANDLE hDIB)
{
BITMAPFILEHEADER hdr;
LPBITMAPINFOHEADER lpbi;
 
if (!hDIB)
{
OutputDebugString(TEXT("No image in hDIB\n"));
return FALSE;
}
 
CFile file;
if( !file.Open( szFile, CFile::modeWrite|CFile::modeCreate) )
{
OutputDebugString(TEXT("Error opening the file..\n"));
return FALSE;
}
 
lpbi = (LPBITMAPINFOHEADER)hDIB;
 
int nColors = 1 << lpbi->biBitCount;
 
// Fill in the fields of the file header
hdr.bfType = ((WORD) ('M' << 8) | 'B'); // is always "BM"
hdr.bfSize = GlobalSize (hDIB) + sizeof( hdr );
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = (DWORD) (sizeof( hdr ) + lpbi->biBitCount +
nColors * sizeof(RGBQUAD));
 
// Write the file header
file.Write( &hdr, sizeof(hdr) );
 
// Write the DIB header and the bits
file.Write( lpbi, GlobalSize(hDIB) );
 
return TRUE;
}

 
I pass the bmp file name and the hBitmap handle to the above function, and i get the following error at run-time:
 
First-chance exception at 0x0041c600 in LPR.exe: 0xC0000005: Access violation reading location 0xccccccda.
Unhandled exception at 0x0041c600 in LPR.exe: 0xC0000005: Access violation reading location 0xccccccda.
 
on line:
int nColors = 1 << lpbi->biBitCount;
 
I've been trying to figure out what have i done wrong and where.. but so far i am unable to find out. So any help regarding this shall be highly appreciated.
 
[The above code has been taken from: http://www.codeguru.com/Cpp/G-M/bitmap/article.php/c1697/ ]
Questionhow to grab images from .mov filesmembersrkrishna25-Jan-05 4:23 
I reffered this code very much........
But i unable to load .mov files into "RenderFile" method...
 
It is not given error .But i tracing the code gives this error
 
Error:- 0x80040111 ClassFactory cannot supply requested class
Here i give sure .mov file exist
 
Plz some body help me.........

 
sivaramakrishna.b
GeneralNo Video and Audiomemberbozitaai11-Jan-05 19:32 
This project was built in DirectX 9.
 
When I press "Grab" button, only the first frame was displayed and no more.
Why can't play the movie and no audio signal?
 
Thank you!
Generali got this error while building this projectmemberslucky18-Dec-04 15:19 
FrameGrabberDemoDlg.obj : error LNK2001: unresolved external symbol _IID_ISampleGrabber
FrameGrabberDemoDlg.obj : error LNK2001: unresolved external symbol _CLSID_SampleGrabber
Debug/FrameGrabberDemo.exe : fatal error LNK1120: 2 unresolved externals
 
How to solve it? plz help me
 
Gone 2 faR !!!
GeneralRe: i got this error while building this projectmemberJohn4420-Dec-04 20:59 

Here is the solution:
 
1. Open the VS-project in Samples\C++\DirectShow\BaseClasses
2. Compile it as Win32 Release
3. Copy the Release\Strmbase.lib file into your DirectX SDK\lib folder
4. Add #pragma comment(lib,"strmbase.lib") below the #include directives in your header file
 
Have fun!

GeneralRe: i got this error while building this projectmemberpig head xiaoma8-Jun-05 17:38 
Hi John,
I've tested the method of the ISampleGrabber,and also I accomplished Extracting bitmaps from a virtual camera.Now I just wonder whether the ISampleGrabber filter can be used in mobile devices? eg:Smartphone?
Thanks a lot and looking forward to your reply~
 
Poke tongue | ;-P :->
 
siwlyfe
GeneralRe: i got this error while building this projectmemberJohn449-Jun-05 23:36 
Hi,
 
AFAIK there is no DirectX implementation for mobile devices (yet). So you can't use the ISampleGrabber filter or any other DirectX related stuff in PDAs, phones, or other mobile devices. The only thing I found is DirectPlay for Pocket PCs, but this won't help you...
 
John
GeneralRe: i got this error while building this projectmemberSurindra5-Jun-07 19:54 
yes u can use ISampleGrabber with mobile devices...WM 5.0 smartphone , etc.i have tried it.
QuestionRe: i got this error while building this projectmemberside218-Jun-07 6:18 
Could you post some code describing how to use ISampleGrabber in Windows Mobile 5?
QuestionRe: i got this error while building this projectmemberbrianA493-Oct-06 9:55 
I've tried this solution, without any luck. Do you have any other hints or suggestions? Sigh | :sigh:
GeneralRe: i got this error while building this projectmembernicostar20-Dec-04 21:39 
you can solve this this problem by linking strmiids.lib instead of strmbase.lib...;)

GeneralRe: i got this error while building this projectmemberAndrey_Mark19-Aug-09 5:06 
No need to link with Strmbase.lib - this library is big and not needed for this project.
Link only with Strmiids.lib to link with GUIDs.
 
Andrey.
 
- - -

GeneralCompressed Files, HOW GRABBERsussAnonymous21-Sep-04 18:53 
Does anybody knows how to grabbing compressed files (mpeg4, DIVX, XVID, etc..)

Generalfor audio datamemberslampiggy27-May-04 8:53 
I am extracting both video and audio data from a movie file for further analysis. Do I need to use DV splitter or I can just create two sample grabber filter for the source filter? Now when I am trying to connect the source filter to a sample grabber (with simply setting the sample grabber Mediatype MEDIATYPE_Audio), I got a VFW_S_PARTIAL_RENDER error at the pGraph->connect(..) part. Does anybody have idea? Thanks lot!
GeneralOnly Sound no Picsmemberwijesijp19-May-04 20:06 
I can only hear sounds but I can’t see any pictures.
And the application is frozen. Can’t do anything…
 
What should I do?
 
Janaka

GeneralGuidancememberChivalrous13-Apr-04 19:20 
Dear Sir,
 
I am a final year student of Karachi, Pakistan. I am working on a Motion Detection System, which is capable of detecting meaningful motion in an Area where human motion is prohibited. First it needs to grab each and every frame and then involves image processing on each and every frame. Application of different filters and a lot.
Please recommend me suitable platforms, language and any other thing that could help me.
 
Please guide me
Wishing for a reply.
 
Thanks a lot.
M.Adil Hayat Khan

Generali can't run FrameGrabberDemomemberangel4119-Mar-04 16:26 
every friend,i dowload this demo but when i open one avi file,i can't see this file in the display window .Who may tell me the reason. Thank you very much
 
wew
GeneralRe: i can't run FrameGrabberDemomemberMarkus Axelsson10-Mar-04 10:40 
Hello there!
 
The demo application always tries to extract the frame one second into the movie. Some codecs don't support framegrabbing at every frame. The correct way to do this is to find the nearest frame the graph can seek to and grabe that frame. If I remeber correct there is a method called "CanSeek" or something like that and this method would tell you wich frame to grab.
 
If you are going to compile the project you have to change the libraries linked to the project. Check out some older messages in the article discussion to find out howto do this.
 
/M
QuestionCan not run properly in DirectX 9memberyouken30-Dec-03 17:10 
Through debug, I find the sentence "pMediaControl->Run()" will be wrong in DirectX 9. The return value of the function Run() is not 0 but 1. The program is only compatible with DirectX 8. How to resolve?
GeneralInserting a Frame.!membernewnick16-Dec-03 17:45 
Hi .!,
How can I insert a frame at some specified time position of a movie file.?
 
Thanks in Advance!
 
Warm Regards,
NICK.
GeneralEasy way to do same...memberyooyo3d9-Dec-03 12:18 
Just use IMediaDet...
 

 
yooyo
GeneralHe's right IMediaDet is the way to gomembersaltynuts200231-Dec-04 15:15 
Use IMediaDet in the directx sdk. Easy as pie
GeneralSolution for most of Errormembersriniss8-Dec-03 20:32 
actually strmbasd.lib file is used in the input linker libraries. But it has some error. Better to use strmiids.lib. and remove the strmbasd.lib
 
Go to Project Settings or Properties
and then linker settings
and then Input libraries
Add Strmiids.lib
remove strmbasd.lib
 

 

 


 
srinss
GeneralRe: Solution for most of ErrorsussAnonymous2-Jan-04 5:52 
Which version of directX has this error? I couldn't find any documentation on it.
Questionhow to extract clip of specified duration out of an avi or anyother filememberhina_askh2-Dec-03 15:05 
how to extract clips frm a file
Generalvideo doesn't playmembertoms2k10-Nov-03 2:40 
Is the video supposed to start to play when opening the file?
When I open a file everything stays grey and the grab doesn't work, either. Am I missing something here?
TiA!
- Tom
GeneralRe: video doesn't playmemberDeeKe15-Nov-03 22:00 
Me too..
GeneralRe: video doesn't playmembernobird2-Dec-03 21:14 
oh... me too~~!!!
Anyone helps??
GeneralRe: video doesn't playmemberkurtas2-Nov-05 9:06 
ohhh me tooooo !!!

GeneralRe: video doesn't playsussJabran11-Dec-03 10:47 
Same problem here, please some one can tell the reason or solution ??
 
Confused | :confused:
 
Thanks.
 
Jabran Asghar

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130617.1 | Last Updated 5 Sep 2001
Article Copyright 2001 by Markus Axelsson
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid