Getting a still picture with SampleGrabber
This page shows you how to grab an still image from a video file, using SampleGrabber. Please note that error handling codes are omitted to keep the sample code simple.
SampleGrabber
SampleGrabber is a transform filter. To use SampleGrabber, you must add SampleGrabber filter into the Graph. Since SampleGrabber grabs a frame directly, it has much versatility than IBasicVideo::GetCurrentImage.
To use SampleGrabber, your DirectX version must use at least DirectX8.
Sample code
The following sample code shows how to use SampleGrabber. This sample saves the grabbed video frame as a bitmap file. Please note that saving the video frame is in this sample just to make it easily understandable, and it is not a required function to use SampleGrabber.
#include <stdio.h>
#include <dshow.h>
#include <qedit.h> // for SampleGrabber
#define FILENAME L"C:\\DXSDK\\Samples\\Media\\butterfly.mpg"
int
main()
{
IGraphBuilder *pGraphBuilder;
IMediaControl *pMediaControl;
IBaseFilter *pSampleGrabberFilter;
ISampleGrabber *pSampleGrabber;
AM_MEDIA_TYPE am_media_type;
// initialize COM
CoInitialize(NULL);
// create FilterGraph
CoCreateInstance(CLSID_FilterGraph,
NULL,
CLSCTX_INPROC,
IID_IGraphBuilder,
(LPVOID *)&pGraphBuilder);
// create SampleGrabber(Filter)
CoCreateInstance(CLSID_SampleGrabber,
NULL,
CLSCTX_INPROC,
IID_IBaseFilter,
(LPVOID *)&pSampleGrabberFilter);
// get ISampleGrabber interface from the Filter
pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber,
(LPVOID *)&pSampleGrabber);
// determine the format for connecting SampleGrabber.
// You can configure the SampleGrabber insertion place
// by changing the values in this structure.
// If you use the values in this sample,
// you can get the video frame data right before
// it is displayed.
ZeroMemory(&am_media_type, sizeof(am_media_type));
am_media_type.majortype = MEDIATYPE_Video;
am_media_type.subtype = MEDIASUBTYPE_RGB24;
am_media_type.formattype = FORMAT_VideoInfo;
pSampleGrabber->SetMediaType(&am_media_type);
// add SampleGrabber Filter to the Graph
pGraphBuilder->AddFilter(pSampleGrabberFilter,
L"Sample Grabber");
// get MediaControl
pGraphBuilder->QueryInterface(IID_IMediaControl,
(LPVOID *)&pMediaControl);
// create Graph.
// Graph that contains SampleGrabber
// will be created automatically.
pMediaControl->RenderFile(FILENAME);
// Get connection information.
// This must be done after the Graph is created
// by RenderFile.
pSampleGrabber->GetConnectedMediaType(&am_media_type);
VIDEOINFOHEADER *pVideoInfoHeader =
(VIDEOINFOHEADER *)am_media_type.pbFormat;
// Print the width and height of the image.
// This is just to make the sample understandable.
// This is not a required feature.
printf("size = %dx%d\n",
pVideoInfoHeader->bmiHeader.biWidth,
pVideoInfoHeader->bmiHeader.biHeight);
// Print the data size.
// This is just for understanding too.
printf("sample size = %d\n",
am_media_type.lSampleSize);
// Configure SampleGrabber to do grabbing.
// Buffer data can not be obtained if you
// do not use SetBufferSamples.
// You can use SetBufferSamples after Run() too.
pSampleGrabber->SetBufferSamples(TRUE);
// Start playing
pMediaControl->Run();
// Block execution
MessageBox(NULL,
"Block Execution",
"Block",
MB_OK);
// BITMAP will be saved after OK is pressed
// prepare buffer
long nBufferSize = am_media_type.lSampleSize;
long *pBuffer = (long *)malloc(nBufferSize);
// grab image data.
pSampleGrabber->GetCurrentBuffer(&nBufferSize,
pBuffer);
//
// Save image data as Bitmap.
// This is just to make this sample easily understandable.
//
HANDLE fh;
BITMAPFILEHEADER bmphdr;
DWORD nWritten;
memset(&bmphdr, 0, sizeof(bmphdr));
bmphdr.bfType = ('M' << 8) | 'B';
bmphdr.bfSize = sizeof(bmphdr) + sizeof(BITMAPINFOHEADER) + nBufferSize;
bmphdr.bfOffBits = sizeof(bmphdr) + sizeof(BITMAPINFOHEADER);
fh = CreateFile("result.bmp",
GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(fh, &bmphdr, sizeof(bmphdr), &nWritten, NULL);
WriteFile(fh,
&pVideoInfoHeader->bmiHeader,
sizeof(BITMAPINFOHEADER), &nWritten, NULL);
WriteFile(fh, pBuffer, nBufferSize, &nWritten, NULL);
CloseHandle(fh);
free(pBuffer);
// Release
pSampleGrabber->Release();
pSampleGrabberFilter->Release();
pMediaControl->Release();
pGraphBuilder->Release();
// finish COM
CoUninitialize();
return 0;
}
This sample saves the video frame as a bitmap file named "result.bmp". Please check the created bitmap file when you try this sample. The bitmap file format is explained here.