This is retired content. This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This content may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.
A version of this page is also available for

You can use the Windows Media encoder DMO to write your captured data to an Advanced Systems Format (ASF) file.

Step 1

The first step in the process is to do some general setup by declaring variables, instantiating objects, and obtaining interface pointers.

Copy Code
// Declare pointers to DirectShow interfaces
CComPtr<ICaptureGraphBuilder2>  pCaptureGraphBuilder;
CComPtr<IBaseFilter> 		pVideoCap, pAsfWriter,
								pVideoEncoder, pAudioEncoder;
CComPtr<IBaseFilter> 		pAudioCaptureFilter;
CComPtr<IDMOWrapperFilter> pVideoWrapperFilter,
CComPtr<IPersistPropertyBag> pPropertyBag;
CComPtr<IGraphBuilder> 	pGraph;
CComPtr<IMediaControl> 	pMediaControl;
CComPtr<IMediaEvent> 		pMediaEvent;
CComPtr<IMediaSeeking> 	pMediaSeeking;
CComPtr<IFileSinkFilter> 	pFileSink;

// Create the graph builder and the filtergraph
pCaptureGraphBuilder.CoCreateInstance( CLSID_CaptureGraphBuilder );
pGraph.CoCreateInstance( CLSID_FilterGraph );
pCaptureGraphBuilder->SetFiltergraph( pGraph );

// Query all the interfaces needed later
pGraph.QueryInterface( &pMediaControl );
pGraph.QueryInterface( &pMediaEvent );
pGraph.QueryInterface( &pMediaSeeking );

Step 2

To initialize the video capture filter, you must determine the name of the capture device and then pass that device name to the capture filter.

In the following code, PropBag is an object that implements an IPropertyBaginterface that is used to pass information to the capture filter.

Copy Code
// Initialize the video capture filter
pVideoCap.CoCreateInstance( CLSID_VideoCapture )); 
pVideoCap.QueryInterface( &pPropertyBag ));
varCamName = L"CAM1:";
if(( varCamName.vt == VT_BSTR ) == NULL ) {
PropBag.Write( L"VCapName", &varCamName );   
pPropertyBag->Load( &PropBag, NULL );
pGraph->AddFilter( pVideoCap, L"Video capture source" );

Step 3

Once the capture filter knows what capture device to use, you can begin to initialize the audio and video filters. In the following code, video is encoded with the Windows Media Video 9 DMO by using the DMO Wrapper Filter.

Copy Code
// Initialize the audio capture filter
pAudioCaptureFilter.CoCreateInstance( CLSID_AudioCapture );
pAudioCaptureFilter.QueryInterface( &pPropertyBag );
pPropertyBag->Load( NULL, NULL );
pGraph->AddFilter( pAudioCaptureFilter, L"Audio Capture Filter"

// Initialize the Video DMO Wrapper
pVideoEncoder.CoCreateInstance( CLSID_DMOWrapperFilter );
pVideoEncoder.QueryInterface( &pVideoWrapperFilter );

// Load the WMV9 encoder in the DMO Wrapper. 
// To encode in MPEG, replace CLSID_CWMV9EncMediaObject with the 
// CLSID of your DMO
pVideoWrapperFilter->Init( CLSID_CWMV9EncMediaObject,
pGraph->AddFilter( pVideoEncoder, L"WMV9 DMO Encoder" );

// Load ASF multiplexer. 
// To create a MPEG file, change the CLSID_ASFWriter into the GUID
// of your multiplexer
pAsfWriter.CoCreateInstance( CLSID_ASFWriter );
pAsfWriter->QueryInterface( IID_IFileSinkFilter, (void**)
&pFileSink );
pFileSink->SetFileName( L"\\My Documents\\test0.asf", NULL );

Step 4

Once the individual filters are initialized, you can connect their pins together, using the ICaptureGraphBuilder2 interface, pCaptureGraphBuilder.

Copy Code
// Connect the preview pin to the video renderer
pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_PREVIEW,
									NULL, NULL );

// Connect the video capture pin to the multiplexer through the
// video renderer. 
pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_CAPTURE,
									pVideoEncoder, pAsfWriter );

// Connect the audio capture pin to the multiplexer through the
// audio renderer. 
pCaptureGraphBuilder->RenderStream( &PIN_CATEGORY_CAPTURE,
									pAudioEncoder, pAsfWriter );

Step 5

With all the filters initialized and all of their pins connected together into a capture graph, you can now being to capture data. The code below first blocks the capture graph and then lets it run for a short period of time prior to actually capturing any data. This give the filter graph time to make sure that all of its buffers are allocated and all processes are synchronized.

Copy Code
// Block the capture.
pCaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE,
									 0, 0 ,0,0 );
pCaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE,
									 0, 0, 0, 0 );

// Let's run the graph and wait one second before capturing. 
Sleep( 1000 );

// Let's capture 5 seconds of data in a file
OutputDebugString( L"Starting to capture the first file" );
pCaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE,
									 &dwStart, &dwEnd, 0, 0
pCaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE,
									 &dwStart, &dwEnd, 0, 0

// Wait 5 seconds. 
Sleep( 5000 );

OutputDebugString( L"Stopping the capture" );
pMediaSeeking->GetCurrentPosition( &dwEnd );
pCaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE,
									 &dwStart, &dwEnd, 1, 2
pCaptureGraphBuilder->ControlStream( &PIN_CATEGORY_CAPTURE,
									 &dwStart, &dwEnd, 1, 2

// Wait for the ControlStream event. 
OutputDebugString( L"Wating for the control stream events" );
	pMediaEvent->GetEvent( &lEventCode, &lParam1,
&lParam2, INFINITE );
	pMediaEvent->FreeEventParams( lEventCode, lParam1, lParam2

	if( lEventCode == EC_STREAM_CONTROL_STOPPED ) {
		OutputDebugString( L"Received a control stream stop event"
} while( count < 2);

OutputDebugString( L"The file has been captured" );

See Also