Getting the first frame with SampleGrabber

This page shows you how to grab the first video frame into a still image file, using SampleGrabber. Please note that error handling codes are omitted to keep the sample code simple.

Sample code

This sample will save the first video frame, and after the first video frame is captured, the graph will automatically stop running. The previous samples used MessageBox to prevent the graph from stopping, but this sample uses WaitForCompletion instead.



#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);

 //
 // you can use SetOneShot(TRUE) to force graph to 
 // stop after grabbing one picture.
 //
 pSampleGrabber->SetOneShot(TRUE);

 // start playing
 pMediaControl->Run();

 //
 // wait for graph to finish
 //
 IMediaEvent *pEvent;
 pGraphBuilder->QueryInterface(IID_IMediaEvent,
     (LPVOID *)&pEvent);

 long evCode;
 pEvent->WaitForCompletion(INFINITE, &evCode);


 // 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();

 // finalize COM
 CoUninitialize();

 return 0;
}


This sample saves the first video frame as result.bmp. Please check the bitmap file created after executing this test application.

This sample uses the SetOneShot API to grab the first frame in the video file. In this sample, WaitForCompletion is used to wait for the Graph to grab one frame. For more information about WaitForCompletion, please see "Waiting for the end of media".

  

Copyright (C) GeekPage.JP. All rights reserved.