CoInitialize(NULL);
HRESULT hr;
IGraphBuilder* pGraphBuilder=NULL;
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&pGraphBuilder);
IBaseFilter* pMpeg4PSFileStream;
IBaseFilter* pMpegDemuxFilter;
IBaseFilter* pMpeg4VideoDecoder;
IBaseFilter* pOverlayMaxer2;
IBaseFilter* pVideoRenderer;
hr=CoCreateInstance(CLSID_Mpeg4PSFileStream, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pMpeg4PSFileStream);
if (FAILED(hr))
AfxMessageBox("err create CLSID_Mpeg4PSFileStream");
hr=CoCreateInstance(CLSID_MpegDemuxFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pMpegDemuxFilter);
if (FAILED(hr))
AfxMessageBox("err create CLSID_MpegDemuxFilter");
hr=CoCreateInstance(CLSID_Mpeg4VideoDecoder, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pMpeg4VideoDecoder);
if (FAILED(hr))
AfxMessageBox("err create CLSID_Mpeg4VideoDecoder");
hr=CoCreateInstance(CLSID_OverlayMaxer2, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pOverlayMaxer2);
if (FAILED(hr))
AfxMessageBox("err create CLSID_OverlayMaxer2");
hr=CoCreateInstance(CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVideoRenderer);
if (FAILED(hr))
AfxMessageBox("err create CLSID_VideoRenderer");
pGraphBuilder->AddFilter(pMpeg4PSFileStream , NULL);
pGraphBuilder->AddFilter(pMpegDemuxFilter , NULL);
pGraphBuilder->AddFilter(pMpeg4VideoDecoder , NULL);
pGraphBuilder->AddFilter(pOverlayMaxer2 , NULL);
pGraphBuilder->AddFilter(pVideoRenderer , NULL);
//set the source file
IFileSourceFilter * pLoader;
pMpeg4PSFileStream->QueryInterface(IID_IFileSourceFilter, (void **)&pLoader);
hr=pLoader->Load(L"E:\\temp\\mpeg4_ps.mpg",NULL);
if (FAILED(hr))
AfxMessageBox("装载文件出错!");
//connect filter
char *strPinName = new char;
IEnumPins* EnumPins;
IPin* OutPin;
IPin* InPin;
ULONG fetched;
PIN_INFO pinfo;
// find source output
pMpeg4PSFileStream->EnumPins(&EnumPins);
EnumPins->Reset();
EnumPins->Next(1, &OutPin, &fetched); // only 1 pin for source, so we know this is the one we need
EnumPins->Release();
// find Demux Filter input
pMpegDemuxFilter->EnumPins(&EnumPins);
EnumPins->Reset();
EnumPins->Next(1, &InPin, &fetched);
InPin->QueryPinInfo(&pinfo);
pinfo.pFilter->Release(); // make sure you release the returned IBaseFilter interface
while (pinfo.dir == PINDIR_OUTPUT) // check if we have wrong pin (not input pin),2 output pin
{
InPin->Release();
EnumPins->Next(1, &InPin, &fetched); // if so, get next pin
InPin->QueryPinInfo(&pinfo);
pinfo.pFilter->Release();
}
// connect -- 1
pGraphBuilder->Connect(OutPin, InPin);
InPin->Release();
OutPin->Release();
// find Demux Filter output
EnumPins->Reset();
EnumPins->Next(1, &OutPin, &fetched);
OutPin->QueryPinInfo(&pinfo);
pinfo.pFilter->Release();
if (pinfo.dir == PINDIR_INPUT) // check if we have wrong pin (not input pin),only 1 input pin
{
InPin->Release();
EnumPins->Next(1, &OutPin, &fetched); // if so, get next pin
}
EnumPins->Release();
// find Vweb Mpeg4 Video Decoder input
pMpeg4VideoDecoder->EnumPins(&EnumPins);
EnumPins->Reset();
EnumPins->Next(1, &InPin, &fetched);
InPin->QueryPinInfo(&pinfo);
pinfo.pFilter->Release(); // make sure you release the returned IBaseFilter interface
if (pinfo.dir == PINDIR_OUTPUT) // check if we have wrong pin (not input pin),only 1 input pin
{
InPin->Release();
EnumPins->Next(1, &InPin, &fetched); // if so, get next pin
}
// connect -- 2
pGraphBuilder->Connect(OutPin, InPin);
InPin->Release();
OutPin->Release();
// find Vweb Mpeg4 Video Decoder output *****************************************
EnumPins->Reset();
EnumPins->Next(1, &OutPin, &fetched);
OutPin->QueryPinInfo(&pinfo);
pinfo.pFilter->Release(); // make sure you release the returned IBaseFilter interface
if (pinfo.dir == PINDIR_INPUT) // check if we have wrong pin (not input pin),only 1 input pin
{
OutPin->Release();
EnumPins->Next(1, &OutPin, &fetched); // if so, get next pin
OutPin->QueryPinInfo(&pinfo);
pinfo.pFilter->Release();
WCHAR *s=pinfo.achName;
}
EnumPins->Release();
// find Overlay Mixer2 input
pOverlayMaxer2->EnumPins(&EnumPins);
EnumPins->Reset();
EnumPins->Next(1, &InPin, &fetched);
InPin->QueryPinInfo(&pinfo);
pinfo.pFilter->Release(); // make sure you release the returned IBaseFilter interface
WCHAR *s=pinfo.achName;
if (pinfo.dir == PINDIR_OUTPUT) // check if we have wrong pin (not input pin),2 input pin
{
InPin->Release();
EnumPins->Next(1, &InPin, &fetched); // if so, get next pin
}
// connect -- 3
pGraphBuilder->Connect(OutPin, InPin);
InPin->Release();
OutPin->Release();
// find Overlay Mixer2 output
EnumPins->Reset();
EnumPins->Next(1, &OutPin, &fetched);
OutPin->QueryPinInfo(&pinfo);
pinfo.pFilter->Release(); // make sure you release the returned IBaseFilter interface
while (pinfo.dir == PINDIR_INPUT) // check if we have wrong pin (not input pin),2 input pin
{
OutPin->Release();
EnumPins->Next(1, &OutPin, &fetched); // if so, get next pin
OutPin->QueryPinInfo(&pinfo);
pinfo.pFilter->Release();
WCHAR *s=pinfo.achName;
}
EnumPins->Release();
// find renderer input
pVideoRenderer->EnumPins(&EnumPins);
EnumPins->Reset();
EnumPins->Next(1, &InPin, &fetched); // renderer has only 1 pin, so this is the pin we need
EnumPins->Release();
// connect -- 4
pGraphBuilder->Connect(OutPin, InPin);
InPin->Release();
OutPin->Release();
IMediaEvent *pEvent;
IMediaControl *pMediaControl;
// Create the filter graph manager and query for interfaces.
hr=pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
hr=pGraphBuilder->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Run the graph.
pMediaControl->Run();
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Clean up.
pMpeg4PSFileStream->Release();
pMpegDemuxFilter->Release();
pMpeg4VideoDecoder->Release();
pOverlayMaxer2->Release();
pVideoRenderer->Release();
pMediaControl->Release();
pEvent->Release();
pGraphBuilder->Release();
delete strPinName;
CoUninitialize();
HRESULT CCaptureEx::FindCaptureDevice(IBaseFilter **ppSrcFilter)
{
HRESULT hr;
IBaseFilter * pSrc = NULL;
CComPtr <IMoniker> pMoniker =NULL;
ULONG cFetched;
if (!ppSrcFilter)
return E_POINTER;
// Create the system device enumerator
CComPtr <ICreateDevEnum> pDevEnum =NULL;
hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
IID_ICreateDevEnum, (void **) &pDevEnum);
if (FAILED(hr))
{
Msg(TEXT("Couldn't create system enumerator! hr=0x%x"), hr);
return hr;
}
// Create an enumerator for the video capture devices
CComPtr <IEnumMoniker> pClassEnum = NULL;
hr = pDevEnum->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &pClassEnum, 0);
if (FAILED(hr))
{
//Msg(TEXT("Couldn't create class enumerator! hr=0x%x"), hr);
return hr;
}
// If there are no enumerators for the requested type, then
// CreateClassEnumerator will succeed, but pClassEnum will be NULL.
if (pClassEnum == NULL)
{
return E_FAIL;
}
// Use the first video capture device on the device list.
// Note that if the Next() call succeeds but there are no monikers,
// it will return S_FALSE (which is not a failure). Therefore, we
// check that the return code is S_OK instead of using SUCCEEDED() macro.
if (S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched)))
{
// Bind Moniker to a filter object
hr = pMoniker->BindToObject(0,0,IID_IBaseFilter, (void**)&pSrc);
if (FAILED(hr))
{
//Msg(TEXT("Couldn't bind moniker to filter object! hr=0x%x"), hr);
return hr;
}
}
else
{
//Msg(TEXT("Unable to access video capture device!"));
return E_FAIL;
}
// Copy the found filter pointer to the output parameter.
// Do NOT Release() the reference, since it will still be used
// by the calling function.
*ppSrcFilter = pSrc;
return hr;
}
/ 根据Filter的DisplayName来获取其IMoniker指针,并将IMoniker指针绑定到一个IBaseFilter指针中
HRESULT CDXGraph::DisplayNameToMoniker(WCHAR * szDisplayName, IBaseFilter ** ppBf)
{
if (! mGraph || ! szDisplayName|| ! ppBf)
return E_POINTER;
IBaseFilter *pFilter = NULL;
IBindCtx *pBindCtx;
HRESULT hr = CreateBindCtx(0, &pBindCtx);
ULONG chEaten = 0;
CComPtr <IMoniker> pMoniker = NULL;
hr = MkParseDisplayName(pBindCtx, szDisplayName, &chEaten, &pMoniker);
pBindCtx->Release();
if (SUCCEEDED(hr))
{
hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,(void **)&pFilter);
if (FAILED(hr))
{
AfxMessageBox(TEXT("Couldn't bind moniker to filter object!"));
return E_FAIL;
}
// Copy the found filter pointer to the output parameter.
// Do NOT Release() the reference, since it will still be used
// by the calling function.
*ppBf = pFilter;
return hr;
}
return hr;
}
//使用xvid mpge4的代码,其中szDisplay存储的是Filter的DisplayName,可以重GraphEdit中查看
WCHAR szDisplay[] = L"@device:cm:{33D9A760-90C8-11D0-BD43-00A0C911CE86}\\xvid";
if (SUCCEEDED(mFilterGraph->DisplayNameToMoniker(szDisplay, &pVideoCompressFilter)))
{
if (SUCCEEDED(mFilterGraph->GetGraph()->AddFilter(pVideoCompressFilter,L"XVid MPEG-4 Codec")))
{
//pVideoCompressFilter->Release();
}
}
// 获取视频采集的Capture Source Filter和FriendlyName
HRESULT CDXGraph::EnumVideoCaptureSource(IBaseFilter ** ppBf, WCHAR* szFilterName)
{
if (!mGraph || ! ppBf)
return E_POINTER;
// Create the System Device Enumerator.
IBaseFilter *pFilter = NULL;
HRESULT hr;
CComPtr <ICreateDevEnum> pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void **)&pSysDevEnum);
if (FAILED(hr))
{
return hr;
}
// Obtain a class enumerator for the video capture Source category.
CComPtr <IEnumMoniker> pEnumCat = NULL;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
if (FAILED(hr))
{
AfxMessageBox("Create class enumerator for the video capture Failed.");
return hr;
}
// If there are no enumerators for the requested type, then
// CreateClassEnumerator will succeed, but pClassEnum will be NULL.
if (pEnumCat == NULL)
{
CString str("");
str += TEXT("No video capture device was detected.\r\n\r\n");
str += TEXT("This sample requires a video capture device, such as a USB WebCam,\r\n");
str += TEXT("This sample requires a video capture device, such as a USB WebCam,\r\n");
str += TEXT("This sample requires a video capture device, such as a USB WebCam,\r\n");
str += TEXT("to be installed and working properly. The sample will now close.");
AfxMessageBox(str);
return E_FAIL;
}
// Use the first video capture device on the device list.
// Note that if the Next() call succeeds but there are no monikers,
// it will return S_FALSE (which is not a failure). Therefore, we
// check that the return code is S_OK instead of using SUCCEEDED() macro.
CComPtr <IMoniker> pMoniker = NULL;
ULONG cFetched;
if(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
{
IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
(void **)&pPropBag);
if (SUCCEEDED(hr))
{
// To retrieve the filter's friendly name, do the following:
VARIANT varName;
VariantInit(&varName);
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
if (SUCCEEDED(hr))
{
// Display the name in your UI somehow.
//使用W2A()、A2W()、T2OLE()、OLE2T()等转换函数需要使用USES_CONVERSION语句
USES_CONVERSION;
//varName.bstrVal的值为局部变量,需要将数据复制到数组变量中
//如果使用指针指向局部变量,则产生错误
wsprintfW(szFilterName,varName.bstrVal);
//AfxMessageBox(W2A(szFilterName));
}
VariantClear(&varName);
pPropBag->Release();
// To create an instance of the filter, do the following:
hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,(void **)&pFilter);
if (FAILED(hr))
{
AfxMessageBox(TEXT("Couldn't bind moniker to filter object!"));
return hr;
}
}
else
{
AfxMessageBox(TEXT("Unable to access video capture device!"));
return E_FAIL;
}
// Copy the found filter pointer to the output parameter.
// Do NOT Release() the reference, since it will still be used
// by the calling function.
*ppBf = pFilter;
return hr;
}
return hr;
}