2024年2月7日发(作者:)

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:tempmpeg4_",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);

r->Release(); // make sure you release the returned

IBaseFilter interface

while ( == 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);

r->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);

r->Release();

if ( == 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);

r->Release(); // make sure you release the returned

IBaseFilter interface

if ( == 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);

r->Release(); // make sure you release the returned

IBaseFilter interface

if ( == 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);

r->Release();

WCHAR *s=e;

}

EnumPins->Release();

// find Overlay Mixer2 input

pOverlayMaxer2->EnumPins(&EnumPins);

EnumPins->Reset();

EnumPins->Next(1, &InPin, &fetched);

InPin->QueryPinInfo(&pinfo);

r->Release(); // make sure you release the returned

IBaseFilter interface

WCHAR *s=e;

if ( == 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);

r->Release(); // make sure you release the returned

IBaseFilter interface

while ( == 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);

r->Release();

WCHAR *s=e;

}

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();

长枪大戟的代码都已经包括了,不过听说不在directshow filter里的filter需要枚举才能正常使用,但是我没有试过,不知道是不是,以下代码是枚举捕捉设备的.

HRESULT CCaptureEx::FindCaptureDevice(IBaseFilter **ppSrcFilter)

{

HRESULT hr;

IBaseFilter * pSrc = NULL;

CComPtr pMoniker =NULL;

ULONG cFetched;

if (!ppSrcFilter)

return E_POINTER;

// Create the system device enumerator

CComPtr 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 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 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 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 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 ");

str += TEXT("This sample requires a video capture device, such as a USB

WebCam,rn");

str += TEXT("This sample requires a video capture device, such as a USB

WebCam,rn");

str += TEXT("This sample requires a video capture device, such as a USB

WebCam,rn");

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 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;

//l的值为局部变量,需要将数据复制到数组变量中

//如果使用指针指向局部变量,则产生错误

wsprintfW(szFilterName,l);

//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;

}