用摄像头预览过程如下:
ICaptureGraphBuilder2 *pBuild; // Capture Graph Builder // Initialize pBuild (not shown). IBaseFilter *pCap; // Video capture filter. /* Initialize pCap and add it to the filter graph (not shown). */ hr = pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap, NULL, NULL);
HRESULT InitCaptureGraphBuilder( IGraphBuilder **ppGraph, // Receives the pointer. ICaptureGraphBuilder2 **ppBuild // Receives the pointer. ) { if (!ppGraph || !ppBuild) { return E_POINTER; } IGraphBuilder *pGraph = NULL; ICaptureGraphBuilder2 *pBuild = NULL; // Create the Capture Graph Builder. HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild ); if (SUCCEEDED(hr)) { // Create the Filter Graph Manager. hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph); if (SUCCEEDED(hr)) { // Initialize the Capture Graph Builder. pBuild->SetFiltergraph(pGraph); // Return both interface pointers to the caller. *ppBuild = pBuild; *ppGraph = pGraph; // The caller must release both interfaces. return S_OK; } else { pBuild->Release(); } } return hr; // Failed }
ICreateDevEnum *pDevEnum = NULL; IEnumMoniker *pEnum = NULL; // Create the System Device Enumerator. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast<void**>(&pDevEnum)); if (SUCCEEDED(hr)) { // Create an enumerator for the video capture category. hr = pDevEnum->CreateClassEnumerator( CLSID_VideoInputDeviceCategory, &pEnum, 0); }
HWND hList; // Handle to the list box. IMoniker *pMoniker = NULL; while (pEnum->Next(1, &pMoniker, NULL) == S_OK) { IPropertyBag *pPropBag; hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag)); if (FAILED(hr)) { pMoniker->Release(); continue; // Skip this one, maybe the next one will work. } // Find the description or friendly name. VARIANT varName; VariantInit(&varName); hr = pPropBag->Read(L"Description", &varName, 0); if (FAILED(hr)) { hr = pPropBag->Read(L"FriendlyName", &varName, 0); } if (SUCCEEDED(hr)) { // Add it to the application's list box. USES_CONVERSION; (long)SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)OLE2T(varName.bstrVal)); VariantClear(&varName); } pPropBag->Release(); pMoniker->Release(); }
IBaseFilter *pCap = NULL; hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap); if (SUCCEEDED(hr)) { hr = m_pGraph->AddFilter(pCap, L"Capture Filter"); }
HRESULT InitCaptureGraphBuilder( IGraphBuilder **ppGraph, // Receives the pointer. ICaptureGraphBuilder2 **ppBuild // Receives the pointer. ) { if (!ppGraph || !ppBuild) { return E_POINTER; } IGraphBuilder *pGraph = NULL; ICaptureGraphBuilder2 *pBuild = NULL; // Create the Capture Graph Builder. HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild ); if (SUCCEEDED(hr)) { // Create the Filter Graph Manager. hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph); if (SUCCEEDED(hr)) { // Initialize the Capture Graph Builder. pBuild->SetFiltergraph(pGraph); // Return both interface pointers to the caller. *ppBuild = pBuild; *ppGraph = pGraph; // The caller must release both interfaces. return S_OK; } else { pBuild->Release(); } } return hr; // Failed } HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum) { ICreateDevEnum *pDevEnum = NULL; // Create the System Device Enumerator. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast<void**>(&pDevEnum)); if (SUCCEEDED(hr)) { // Create an enumerator for the video capture category. hr = pDevEnum->CreateClassEnumerator( CLSID_VideoInputDeviceCategory, ppEnum, 0); } return hr; } void DisplayDeviceInformation(IEnumMoniker *pEnum, IMoniker** pMoniker) { HWND hList; // Handle to the list box. while (pEnum->Next(1, pMoniker, NULL) == S_OK) { IPropertyBag *pPropBag; HRESULT hr = (*pMoniker)->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag)); if (FAILED(hr)) { (*pMoniker)->Release(); continue; // Skip this one, maybe the next one will work. } // Find the description or friendly name. VARIANT varName; VariantInit(&varName); hr = pPropBag->Read(L"Description", &varName, 0); if (FAILED(hr)) { hr = pPropBag->Read(L"FriendlyName", &varName, 0); } if (SUCCEEDED(hr)) { // Add it to the application's list box. USES_CONVERSION; /*(long)SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)OLE2T(varName.bstrVal));*/ VariantClear(&varName); } pPropBag->Release(); (*pMoniker)->Release(); } }
ICaptureGraphBuilder2 *pBuild; IGraphBuilder *ppGraph; IMoniker* pMoniker; IMediaControl *pControl; IMediaEvent *pEvent; InitCaptureGraphBuilder(&ppGraph,&pBuild); hr = ppGraph->QueryInterface(IID_IMediaControl, (void **)&pControl); hr = ppGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent); IBaseFilter *pCap; // Video capture filter. IEnumMoniker *pEnum; hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum); DisplayDeviceInformation(pEnum, &pMoniker); hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap); if (SUCCEEDED(hr)) { hr = ppGraph->AddFilter(pCap, L"Capture Filter"); } hr = pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap, NULL, NULL); hr = pControl->Run();
接下就是把捕获的视频进行保存了
IBaseFilter *pMux;
hr = pBuild->SetOutputFileName(&MEDIASUBTYPE_Avi,L"D:\\Example.avi",&pMux,NULL);
hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,pCap,NULL,pMux);
程序调试了很久,刚开始链路是正确的,但是没办法播放,原因是存放地址放在了C盘,可能是win7 系统权限问题,修改保存路径到D盘就可以了。
如果需要对文件先进行编码,然后保存,代码如下:
Specify the encoder filter as the fourth parameter to RenderStream, shown in bold in the following example: IBaseFilter *pEncoder; /* Create the encoder filter (not shown). */ // Add it to the filter graph. pGraph->AddFilter(pEncoder, L"Encoder); /* Call SetOutputFileName as shown previously. */ // Render the stream. hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pCap, pEncoder, pMux); pEncoder->Release();