アップルトンの答えは正しいです。私はその答えを拡張し、手動で作成されたDirectShowグラフのフィルターをインスタンス化する方法を示すサンプルコード(C ++ / CLI)を提供しています(利用可能なまばらなドキュメントから断片をピックアップするのは時間がかかる場合があります)。関連するコードは、REDUCE_FRAME_RATE
条件付きでコンパイルされたコード内にあります。COM_CALL()
私のカスタムHRESULTチェックマクロです。
// Additional include files required for DMO support
#include <ParserUIDs.h>
#include <dmodshow.h>
#include <propsys.h>
…
static void AddDecodedVideoSampleGrabber(
AVStreamSourceBox^ sourceBox,
IGraphBuilder* pGraph,
CComPtr<IBaseFilter>& pDecodedVideoSampleGrabber,
IPin* pSourcePin,
CComPtr<IPin>& pDecodedVideoSampleGrabberOutPin
) {
HRESULT hRes;
COM_CALL(pDecodedVideoSampleGrabber.CoCreateInstance(CLSID_SampleGrabber));
COM_CALL(pGraph->AddFilter(pDecodedVideoSampleGrabber, L"DecodedVideoSampleGrabber"));
CComPtr<IPin> pDecodedVideoSampleGrabberInPin(FilterTools::GetPin(pDecodedVideoSampleGrabber, "Input"));
COM_CALL(pGraph->ConnectDirect(pSourcePin, pDecodedVideoSampleGrabberInPin, NULL));
pDecodedVideoSampleGrabberOutPin = FilterTools::GetPin(pDecodedVideoSampleGrabber, "Output");
auto pFrameCallbackSink = (SampleGrabberCBSink*)sourceBox->SetupSampleGrabberCallback(
FRAME_SAMPLE_GRABBER,
IntPtr(pDecodedVideoSampleGrabber)
).ToPointer();
sourceBox->SetDecodedVideoSampleGrabber(IntPtr(pFrameCallbackSink));
#ifdef REDUCE_FRAME_RATE
// insert frame-reduction filter before x264 encoding
CComPtr<IBaseFilter> pFrameReducer;
COM_CALL(pFrameReducer.CoCreateInstance(CLSID_DMOWrapperFilter));
COM_CALL(pGraph->AddFilter(pFrameReducer, L"FrameReducer"));
CComPtr<IDMOWrapperFilter> pDmoWrapper;
COM_CALL(pFrameReducer->QueryInterface(__uuidof(IDMOWrapperFilter), (void**)&pDmoWrapper));
COM_CALL(pDmoWrapper->Init(__uuidof(CFrameRateConvertDmo), DMOCATEGORY_VIDEO_EFFECT));
CComPtr<IPropertyStore> pPropStore;
COM_CALL(pFrameReducer->QueryInterface(IID_PPV_ARGS(&pPropStore)));
PROPVARIANT var;
PropVariantInit(&var);
var.vt = VT_UI8;
var.uhVal.HighPart = OUTPUT_FPS; // Desired frame rate
var.uhVal.LowPart = 1;
pPropStore->SetValue(MFPKEY_CONV_OUTPUTFRAMERATE, var);
PropVariantClear(&var);
CComPtr<IPin>&pDmoInPin(FilterTools::GetPin(pFrameReducer, "in0"));
COM_CALL(pGraph->ConnectDirect(pDecodedVideoSampleGrabberOutPin, pDmoInPin, NULL));
CComPtr<IPin>&pDmoOutPin(FilterTools::GetPin(pFrameReducer, "out0"));
pDecodedVideoSampleGrabberOutPin = pDmoOutPin;
#endif
}