Microsoft DirectX 8.1 (C++) |
After you specify the media type, you can build a filter graph that contains the Sample Grabber. The Sample Grabber will only connect using the specified type, and this enables you to use the various Intelligent Connect mechanisms when you build the graph.
For example, the code in the previous section specified uncompressed video frames. Given that, you can grab frames from a video file source by calling the IGraphBuilder::AddSourceFilter method, to insert the source filter, and the IGraphBuilder::Connect method, to connect the source filter to the Sample Grabber. The Filter Graph Manager automatically adds the required decompression filter.
The following code shows how to do this. It uses two helper functions to enumerate the pins on the filter and connect them. The GetPin function finds the first pin on a filter that matches the specified direction, input or output. The ConnectFilters function finds the first output pin on one filter, and connects it to the first input pin on another filter. As you continue to work with filter graphs, you will probably build up your own library of such helper functions.
// Forward declares.
HRESULT GetPin(IBaseFilter *, PIN_DIRECTION, IPin **);
HRESULT ConnectFilters(IGraphBuilder *, IBaseFilter *, IBaseFilter *);
IBaseFilter *pSrc;
hr = pGraph->AddSourceFilter(wszFileName, L"Source", &pSrc);
hr = ConnectTwoFilters(pGraph, pSrc, pF);
// Helper functions:
HRESULT GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin)
{
IEnumPins *pEnum;
IPin *pPin;
pFilter->EnumPins(&pEnum);
while(pEnum->Next(1, &pPin, 0) == S_OK)
{
PIN_DIRECTION PinDirThis;
pPin->QueryDirection(&PinDirThis);
if (PinDir == PinDirThis)
{
pEnum->Release();
*ppPin = pPin;
return S_OK;
}
pPin->Release();
}
pEnum->Release();
return E_FAIL;
}
HRESULT ConnectFilters(IGraphBuilder *pGraph, IBaseFilter *pFirst, IBaseFilter *pSecond)
{
IPin *pOut = NULL, *pIn = NULL;
HRESULT hr = GetPin(pFirst, PINDIR_OUTPUT, &pOut);
if (FAILED(hr)) return hr;
hr = GetPin(pSecond, PINDIR_INPUT, &pIn);
if (FAILED(hr))
{
pOut->Release();
return E_FAIL;
}
hr = pGraph->Connect(pOut, pIn);
pIn->Release();
pOut->Release();
return hr;
}
The application must also connect the Sample Grabber's output pin. If you just want to discard the samples when you are done (instead of rendering them), connect the Null Renderer Filter. The Null Renderer simply discards every sample that it receives.
IBaseFilter *pNull = NULL;
hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, reinterpret_cast<void**>(&pNull));
hr = pGraph->AddFilter(pNull, L"NullRenderer");
hr = ConnectTwoFilters(pGraph, pF, pNull);