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.





Google
Web geekpage.jp
Copyright (C) GeekPage.JP. All rights reserved.