Video frame capture using IBasicVideo
This page shows you how to capture a video frame using IBasicVideo. Please note that error handling codes are omitted to keep the sample code simple.
IBasicVideo::GetCurrentImage
There are 2 ways to grab a video frame. One is using IBasicVideo, and the other is using SampleGrabber. This page shows you howto use IBasicVideo.
Sample code
Please note that the following sample includes some code that is not directly related to IBasicVideo. The sample code saves an bitmap file after pressing the OK button. This is done to make the sample easily understandable. Therefore, you can omit the bmp saving part if you do not need them.
#include <stdio.h>
#include <dshow.h>
// change here
#define FILENAME L"C:\\DXSDK\\Samples\\Media\\butterfly.mpg"
// note that this sample fails on some environment
int
main()
{
IGraphBuilder *pGraphBuilder;
IMediaControl *pMediaControl;
IBasicVideo *pBasicVideo;
CoInitialize(NULL);
CoCreateInstance(CLSID_FilterGraph,
NULL,
CLSCTX_INPROC,
IID_IGraphBuilder,
(LPVOID *)&pGraphBuilder);
pGraphBuilder->QueryInterface(IID_IMediaControl,
(LPVOID *)&pMediaControl);
pMediaControl->RenderFile(FILENAME);
pGraphBuilder->QueryInterface(IID_IBasicVideo,
(LPVOID *)&pBasicVideo);
pMediaControl->Run();
// The image will be saved when OK is clicked
MessageBox(NULL,
"Grab Image",
"Grab",
MB_OK);
// Must Pause before using GetCurrentImage
pMediaControl->Pause();
// get width and height
long height, width;
pBasicVideo->get_VideoHeight(&height);
pBasicVideo->get_VideoWidth(&width);
long bufSize;
long *imgData;
HRESULT hr;
/*
The second value is NULL to resolve required buffer size.
The required buffer size will be returned in variable "bufSize".
*/
hr = pBasicVideo->GetCurrentImage(&bufSize, NULL);
if (FAILED(hr)) {
printf("GetCurrentImage failed\n");
return 1;
}
if (bufSize < 1) {
printf("failed to get data size\n");
return 1;
}
imgData = (long *)malloc(bufSize);
// The data will be in DIB format
pBasicVideo->GetCurrentImage(&bufSize, imgData);
// save DIB file as Bitmap.
// This sample saves image as bitmap to help
// understanding the sample.
HANDLE fh;
BITMAPFILEHEADER bmphdr;
BITMAPINFOHEADER bmpinfo;
DWORD nWritten;
memset(&bmphdr, 0, sizeof(bmphdr));
memset(&bmpinfo, 0, sizeof(bmpinfo));
bmphdr.bfType = ('M' << 8) | 'B';
bmphdr.bfSize = sizeof(bmphdr) + sizeof(bmpinfo) + bufSize;
bmphdr.bfOffBits = sizeof(bmphdr) + sizeof(bmpinfo);
bmpinfo.biSize = sizeof(bmpinfo);
bmpinfo.biWidth = width;
bmpinfo.biHeight = height;
bmpinfo.biPlanes = 1;
bmpinfo.biBitCount = 32;
fh = CreateFile("result.bmp",
GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(fh, &bmphdr, sizeof(bmphdr), &nWritten, NULL);
WriteFile(fh, &bmpinfo, sizeof(bmpinfo), &nWritten, NULL);
WriteFile(fh, imgData, bufSize, &nWritten, NULL);
CloseHandle(fh);
free(imgData);
// Release resource
pBasicVideo->Release();
pMediaControl->Release();
pGraphBuilder->Release();
CoUninitialize();
return 0;
}
This sample creates a bitmap file named "result.bmp". The grabbed video frame is saved as a bitmap image. Please check the output bitmap file after you tried this sample.
IBasicVideo::GetCurrentImage Limitations
Please note that IBasicVideo::GetCurrentImage has some limitations. First of all, GetCurrentImage can only be used when the Graph is in Pause state. Next, it will not work on some hardware/software platform. (It will likely work if your software platform is WindowsXP.)