Microsoft DirectX 8.1 (C++) |
This section describes how to play a media file in Microsoft® DirectShow®. It presents a sample C++ program that plays a media file using only a few lines of code. Playing a file using DirectShow is a four-step process:
To accomplish these steps, you need to use the following COM interfaces:
The filter graph manager implements all of these interfaces.
Start by calling the CoInitialize function, which initializes the COM library. Then call the CoCreateInstance function to create the filter graph manager:
IGraphBuilder *pGraph;
CoInitialize(NULL);
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
The CoCreateInstance function returns a pointer to the filter graph manager's IGraphBuilder interface. Use this interface pointer to query for the other two interfaces that are needed, IMediaControl and IMediaEvent:
IMediaControl *pMediaControl;
IMediaEvent *pEvent;
pGraph->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
Now comes the heart of the program:
pGraph->RenderFile(L"C:\\Example.avi", NULL);
pMediaControl->Run();
pEvent->WaitForCompletion(INFINITE, &evCode);
The IGraphBuilder::RenderFile method constructs a filter graph that will play the specified file. The first parameter is the file name, represented as a wide character (2-byte) Unicode™ string. For simplicity, the example program specifies a literal string, rather than have the user select a file name. The "L" prefix converts an ASCII string to a wide character string. The second parameter is reserved and must equal NULL.
After the filter graph manager has constructed a filter graph, it is ready to begin playback. The IMediaControl::Run method switches the graph into running mode. When the application invokes this method, media data begins to move through the filter graph and is rendered as video, audio, or both.
The IMediaEvent::WaitForCompletion method blocks until the file is done playing. Playback continues on a separate thread. In a real application, you should avoid setting the wait interval to INFINITE, as this can block indefinitely. Also, you might want to respond to other filter graph events. For more information on event handling, see Responding to Events.
Also, in a real application, you should test the return value of RenderFile to confirm that it created the filter graph successfully. For example, if the specified file does not exist, RenderFile fails and returns the error code VFW_E_NOT_FOUND.
Finally, clean up by releasing all the interface pointers and the COM library:
pMediaControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
Sample Code
#include <dshow.h>
void main(void)
{
IGraphBuilder *pGraph;
IMediaControl *pMediaControl;
IMediaEvent *pEvent;
CoInitialize(NULL);
// Create the filter graph manager and query for interfaces.
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
pGraph->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Build the graph. IMPORTANT: Change string to a file on your system.
pGraph->RenderFile(L"C:\\Example.avi", NULL);
// Run the graph.
pMediaControl->Run();
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Clean up.
pMediaControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
}