Hi, I m writing an app that takes a video file as input and extract a frame with a given number from it. I didn't come up with anything original, I just took the GrabBitmaps sample and made some modifications: I added a call pMediaSeeking->SetTimeFormat( &TIME_FORMAT_FRAME ). It works perfectly well for mpg, and avi files. BUT!!! When I feed it an ".wmv" file, it refuses to work. It even writes a really strange line to the console output: "quicktime_open: error in header". I m wondering what does quicktime have to do with Windows Media.
I ve installed MediaFormat SDK, so RenderFile() works just fine on WMV's. the problem emerges when I try to connecs an AsyncReader's output to the SampleGrabber's input. HRESULT = 0x80040217 8 - (
int GrabBitmaps(TCHAR * szFile )
{
USES_CONVERSION;
CComPtr< ISampleGrabber > pGrabber;
CComPtr< IBaseFilter > pSource;
CComPtr< IGraphBuilder > pGraph;
CComPtr< IVideoWindow > pVideoWindow;
HRESULT hr;
// Create the sample grabber
pGrabber.CoCreateInstance( CLSID_SampleGrabber );
if( !pGrabber ) { _tprintf( TEXT("Could not create CLSID_SampleGrabber\r\n") ); return -1; }
CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabberBase( pGrabber );
// Create the file reader
pSource.CoCreateInstance( CLSID_AsyncReader );
if( !pSource ) { _tprintf( TEXT("Could not create source filter\r\n") ); return -1; }
// Create the graph
pGraph.CoCreateInstance( CLSID_FilterGraph );
if( !pGraph ) { _tprintf( TEXT("Could not not create the graph\r\n") ); return -1; }
// Put them in the graph
hr = pGraph->AddFilter( pSource, L"Source" );
hr = pGraph->AddFilter( pGrabberBase, L"Grabber" );
// Load the source
CComQIPtr< IFileSourceFilter, &IID_IFileSourceFilter > pLoad( pSource );
hr = pLoad->Load( T2W( szFile ), NULL );
if( FAILED( hr ) ) { _tprintf( TEXT("Could not load the media file\r\n") ); return -1; }
// Tell the grabber to grab 24-bit video. Must do this
// before connecting it
CMediaType GrabType;
GrabType.SetType( &MEDIATYPE_Video );
GrabType.SetSubtype( &MEDIASUBTYPE_RGB24 );
hr = pGrabber->SetMediaType( &GrabType );
// Get the output pin and the input pin
CComPtr< IPin > pSourcePin;
CComPtr< IPin > pGrabPin;
pSourcePin = GetOutPin( pSource, 0 );
pGrabPin = GetInPin( pGrabberBase, 0 );
// ... and connect them
hr = pGraph->Connect( pSourcePin, pGrabPin ); /* !!!! ##___PROBLEM HERE___## !!!! */
if( FAILED( hr ) ) { _tprintf( TEXT("Could not connect source filter to grabber\r\n") ); return -1; }
// This semi-COM object will receive sample callbacks for us
CSampleGrabberCB CB;
// Ask for the connection media type so we know its size
AM_MEDIA_TYPE mt;
hr = pGrabber->GetConnectedMediaType( &mt );
VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;
CB.Width = vih->bmiHeader.biWidth;
CB.Height = vih->bmiHeader.biHeight;
FreeMediaType( mt );
// Render the grabber output pin (to a video renderer)
CComPtr <IPin> pGrabOutPin = GetOutPin( pGrabberBase, 0 );
hr = pGraph->Render( pGrabOutPin );
if( FAILED( hr ) ) { _tprintf( TEXT("Could not render grabber output pin\r\n") ); return -1; }
// Don't buffer the samples as they pass through
hr = pGrabber->SetBufferSamples( FALSE );
// Only grab one at a time, stop stream after
// grabbing one sample
hr = pGrabber->SetOneShot( TRUE );
// Set the callback, so we can grab the one sample
hr = pGrabber->SetCallback( &CB, 1 );
// Get the seeking interface, so we can seek to a location
CComQIPtr< IMediaSeeking, &IID_IMediaSeeking > pSeeking( pGraph );
hr = pSeeking->IsFormatSupported( &TIME_FORMAT_FRAME );
if ( hr != S_OK ) return 1;
pSeeking->SetTimeFormat( &TIME_FORMAT_FRAME );
// Query the graph for the IVideoWindow interface and use it to
// disable AutoShow. This will prevent the ActiveMovie window from
// being displayed while we grab bitmaps from the running movie.
CComQIPtr< IVideoWindow, &IID_IVideoWindow > pWindow = pGraph;
if (pWindow) { hr = pWindow->put_AutoShow(OAFALSE); }
// set position
REFERENCE_TIME Start = 10;
hr = pSeeking->SetPositions( &Start, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning );
// activate the threads
CComQIPtr< IMediaControl, &IID_IMediaControl > pControl( pGraph );
hr = pControl->Run( );
// wait for the graph to settle
CComQIPtr< IMediaEvent, &IID_IMediaEvent > pEvent( pGraph );
long EvCode = 0;
hr = pEvent->WaitForCompletion( INFINITE, &EvCode );
// callback wrote the sample
_tprintf(TEXT("Sample grabbing complete.\r\n"));
return 0;
}