📄 capturevideo.cpp
字号:
return hr;
}
// @@@@@@@@@
//// Add Capture filter to our graph.
//hr = m_pGraph->AddFilter(pSrcAudioFilter, L"Audio Capture");
//if (FAILED(hr))
//{
// DisplayMesg(TEXT("Couldn't add the capture filter to the graph! hr=0x%x\r\n\r\n")
// TEXT("If you have a working video capture device, please make sure\r\n")
// TEXT("that it is connected and is not being used by another application.\r\n\r\n"), hr);
// pSrcAudioFilter->Release();
// return hr;
//}
// @@@@@@@@@@@@@@@@@@
IBaseFilter *pDSoundRenderer = NULL;
IPin *pFileOut = NULL, *pWAVIn = NULL;
// Now create an instance of the audio renderer
// and obtain a pointer to its IBaseFilter interface.
hr = CoCreateInstance(CLSID_DSoundRender, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter,
(void **)&pDSoundRenderer);
if (SUCCEEDED(hr)) {
// And add the filter to the filter graph
// using the member function AddFilter.
hr = m_pGraph->AddFilter(pDSoundRenderer, L"Audio Renderer");
}
// // Now we need to connect the output pin of the source
// // to the input pin of the renderer.
// // Obtain the output pin of the source filter.
// // The local function GetPin does this.
// pFileOut = GetPin(pSrcFilter/*pInputFileFilter*/, PINDIR_OUTPUT);
//
// if (pFileOut != NULL) { // Is the pin good?
//
// // Obtain the input pin of the WAV renderer.
// pWAVIn = GetPin(pDSoundRenderer, PINDIR_INPUT);
//
// if (pWAVIn != NULL) { // Is the pin good?
//
// // Connect the pins together:
// // We use the Filter Graph Manager's
// // member function Connect,
// // which uses Intelligent Connect.
// // If this fails, DirectShow couldn't
// // render the media file.
//// hr = m_pGraph->Connect(pSrcFilter, pWAVIn);
// }
// }}
// Render the preview pin on the video capture filter
// Use this instead of m_pGraph->RenderFile
hr = m_pCapture->RenderStream (&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
pSrcFilter, NULL, NULL);
if (FAILED(hr))
{
DisplayMesg(TEXT("Couldn't render the video capture stream. hr=0x%x\r\n")
TEXT("The capture device may already be in use by another application.\r\n\r\n")
TEXT("The sample will now close."), hr);
pSrcFilter->Release();
return hr;
}
// @@@@
// hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio,
// pSrcAudioFilter, NULL, NULL);
// if(hr != NOERROR)
// {
// // ErrMsg(TEXT("Cannot render audio capture stream"));
// // goto SetupCaptureFail;
//return hr;
// }
// Now that the filter has been added to the graph and we have
// rendered its stream, we can release this reference to the filter.
pSrcFilter->Release();
// Set video window style and position
hr = SetupVideoWindow();
if (FAILED(hr))
{
DisplayMesg(TEXT("Couldn't initialize video window! hr=0x%x"), hr);
return hr;
}
#ifdef REGISTER_FILTERGRAPH
// Add our graph to the running object table, which will allow
// the GraphEdit application to "spy" on our graph
hr = AddGraphToRot(m_pGraph, &m_dwGraphRegister);
if (FAILED(hr))
{
DisplayMesg(TEXT("Failed to register filter graph with ROT! hr=0x%x"), hr);
m_dwGraphRegister = 0;
}
#endif
// Start previewing video data
hr = m_pMC->Run();
if (FAILED(hr))
{
DisplayMesg(TEXT("Couldn't run the graph! hr=0x%x"), hr);
return hr;
}
SaveGraphFile(m_pGraph, L"C:\\MyGraph1.GRF");
// Remember current state
m_psCurrent = RUNNING;
return S_OK;
}
HRESULT CCaptureVideo::AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
{
IMoniker * pMoniker;
IRunningObjectTable *pROT;
WCHAR wsz[128];
HRESULT hr;
if (!pUnkGraph || !pdwRegister)
return E_POINTER;
if (FAILED(GetRunningObjectTable(0, &pROT)))
return E_FAIL;
wsprintfW(wsz, L"FilterGraph %08x pid %08x\0", (DWORD_PTR)pUnkGraph,
GetCurrentProcessId());
hr = CreateItemMoniker(L"!", wsz, &pMoniker);
if (SUCCEEDED(hr))
{
// Use the ROTFLAGS_REGISTRATIONKEEPSALIVE to ensure a strong reference
// to the object. Using this flag will cause the object to remain
// registered until it is explicitly revoked with the Revoke() method.
//
// Not using this flag means that if GraphEdit remotely connects
// to this graph and then GraphEdit exits, this object registration
// will be deleted, causing future attempts by GraphEdit to fail until
// this application is restarted or until the graph is registered again.
hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph,
pMoniker, pdwRegister);
pMoniker->Release();
}
pROT->Release();
return hr;
}
void CCaptureVideo::RemoveGraphFromRot(DWORD pdwRegister)
{
IRunningObjectTable *pROT;
if (SUCCEEDED(GetRunningObjectTable(0, &pROT)))
{
pROT->Revoke(pdwRegister);
pROT->Release();
}
}
void CCaptureVideo::CloseInterfaces()
{
// Stop previewing data
if (m_pMC)
m_pMC->StopWhenReady();
m_psCurrent = STOPPED;
// Stop receiving events
if (m_pME)
m_pME->SetNotifyWindow(NULL, WM_GRAPHNOTIFY, 0);
// Relinquish ownership (IMPORTANT!) of the video window.
// Failing to call put_Owner can lead to assert failures within
// the video renderer, as it still assumes that it has a valid
// parent window.
if(m_pVW)
{
m_pVW->put_Visible(OAFALSE);
m_pVW->put_Owner(NULL);
}
#ifdef REGISTER_FILTERGRAPH
// Remove filter graph from the running object table
if (m_dwGraphRegister)
RemoveGraphFromRot(m_dwGraphRegister);
#endif
// Release DirectShow interfaces
SAFE_RELEASE(m_pMC);
SAFE_RELEASE(m_pME);
SAFE_RELEASE(m_pVW);
SAFE_RELEASE(m_pGraph);
SAFE_RELEASE(m_pCapture);
}
void CCaptureVideo::CloseInterfacesMoniker()
{
// Stop previewing data
if (m_pMCMoniker)
m_pMCMoniker->StopWhenReady();
// Stop receiving events
if (m_pMEMoniker)
m_pMEMoniker->SetNotifyWindow(NULL, WM_GRAPHNOTIFY, 0);
if(m_pVWMoniker)
{
m_pVWMoniker->put_Visible(OAFALSE);
m_pVWMoniker->put_Owner(NULL);
}
#ifdef REGISTER_FILTERGRAPH
// Remove filter graph from the running object table
if (m_dwGraphRegister)
RemoveGraphFromRotMoniker(m_dwGraphRegister);
#endif
// Release DirectShow interfaces
SAFE_RELEASE(m_pMCMoniker);
SAFE_RELEASE(m_pMEMoniker);
SAFE_RELEASE(m_pVWMoniker);
SAFE_RELEASE(m_pCaptureMoniker);
SAFE_RELEASE(m_pFilterGraph);
}
LRESULT CCaptureVideo::ClearInterfaces(WPARAM wp, LPARAM lp)
{
if( vType == 1) // If WebCam
CloseInterfacesMoniker();
CloseInterfaces();
bVideo = FALSE;
return 0L ;
}
HRESULT CCaptureVideo::GetInterfacesMoniker()
{
HRESULT hr;
if(m_pFilterGraph == NULL)
{
// Create the filter graph
hr = CoCreateInstance (CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IFilterGraph2, (void **) &m_pFilterGraph);
if (FAILED(hr))
return hr;
}
else
{
return E_FAIL ;
}
if(m_pCaptureMoniker == NULL)
{
// Create the capture graph builder
hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,
IID_ICaptureGraphBuilder2, (void **) &m_pCaptureMoniker);
if (FAILED(hr))
return hr;
}
else
return E_FAIL ;
// Obtain interfaces for media control and Video Window
hr = m_pFilterGraph->QueryInterface(IID_IMediaControl,(LPVOID *) &m_pMCMoniker);
if (FAILED(hr))
return hr;
hr = m_pFilterGraph->QueryInterface(IID_IVideoWindow, (LPVOID *) &m_pVWMoniker);
if (FAILED(hr))
return hr;
hr = m_pFilterGraph->QueryInterface(IID_IMediaEvent, (LPVOID *) &m_pMEMoniker);
if (FAILED(hr))
return hr;
// Set the window handle used to process graph events
hr = m_pMEMoniker->SetNotifyWindow((OAHWND)m_hApp, WM_GRAPHNOTIFY, 0);
return hr;
}
HRESULT CCaptureVideo::CaptureVideoByMoniker()
{
HRESULT hr;
IMoniker *pMoniker =NULL;
// Get DirectShow interfaces
hr = GetInterfacesMoniker();
if (FAILED(hr))
{
//Monikor Message
DisplayMesg(TEXT("Failed to get video interfaces! hr=0x%x"), hr);
return hr;
}
// Use the system device enumerator and class enumerator to find
// a moniker that represents a video capture/preview device,
// such as a desktop USB video camera.
hr = FindCaptureDeviceMoniker(&pMoniker);
if (FAILED(hr))
{
//AfxMessageBox("Webcam is not detected.!") ;
return hr;
}
if( nAnalogCount == nVSourceCount )
{
AfxMessageBox("Webcam(USB) is not detected.!") ;
return hr;
}
hr = AddCaptureMonikerToGraph(pMoniker);
if (FAILED(hr))
{
/* DisplayMesg(TEXT("Couldn't add the capture filter to the graph! hr=0x%x\r\n\r\n")
TEXT("If you have a working video capture device, please make sure\r\n")
TEXT("that it is connected and is not being used by another application.\r\n\r\n")
TEXT("The sample will now close."), hr);*/
return hr;
}
// Release the IMoniker interface for the capture source filter
pMoniker->Release();
// Set video window style and position
hr = SetupVideoWindowMoniker();
if (FAILED(hr))
{
DisplayMesg(TEXT("Couldn't initialize video window! hr=0x%x"), hr);
return hr;
}
#ifdef REGISTER_FILTERGRAPH
// Add our graph to the running object table, which will allow
// the GraphEdit application to "spy" on our graph
hr = AddGraphToRotMoniker(m_pFilterGraph, &m_dwGraphRegister);
if (FAILED(hr))
{
DisplayMesg(TEXT("Failed to register filter graph with ROT! hr=0x%x"), hr);
m_dwGraphRegister = 0;
}
#endif
// Start previewing video data
hr = m_pMCMoniker->Run();
if (FAILED(hr))
{
DisplayMesg(TEXT("Couldn't run the graph! hr=0x%x"), hr);
return hr;
}
return S_OK;
}
HRESULT CCaptureVideo::AddCaptureMonikerToGraph(IMoniker *pMoniker)
{
USES_CONVERSION;
HRESULT hr;
IBaseFilter *pBaseFilter=0;
// Get the display name of the moniker
LPOLESTR strMonikerName=0;
hr = pMoniker->GetDisplayName(NULL, NULL, &strMonikerName);
if (FAILED(hr))
{
DisplayMesg(TEXT("Couldn't get moniker's display name! hr=0x%x"), hr);
return hr;
}
#ifdef DEBUG
// Get a human-readable string for evaluation during debugging
TCHAR szMonikerName[256];
_tcsncpy(szMonikerName, W2T(strMonikerName), 255);
szMonikerName[255] = 0; // Null-terminate
//DisplayMesg(TEXT("Moniker: %s\r\n"), szMonikerName);
#endif
// Create a bind context needed for working with the moniker
IBindCtx *pContext=0;
hr = CreateBindCtx(0, &pContext);
if (FAILED(hr))
{
DisplayMesg(TEXT("Couldn't create a bind context for moniker! hr=0x%x"), hr);
return hr;
}
hr = m_pFilterGraph->AddSourceFilterForMoniker(pMoniker, pContext,
strMonikerName, &pBaseFilter);
if (FAILED(hr))
{
DisplayMesg(TEXT("Failed in AddSourceFilterForMoniker()! hr=0x%x"), hr);
return hr;
}
// Attach the filter graph to the capture graph
hr = m_pCaptureMoniker->SetFiltergraph(m_pFilterGraph);
if (FAILED(hr))
{
DisplayMesg(TEXT("Failed to set capture filter graph! hr=0x%x"), hr);
return hr;
}
// Render the preview pin on the video capture filter
// Use this instead of m_pGraph->RenderFile
hr = m_pCaptureMoniker->RenderStream (&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
pBaseFilter, NULL, NULL);
if (FAILED(hr))
{
DisplayMesg(TEXT("Couldn't render capture stream. ")
TEXT("The device may already be in use.\r\n\r\nhr=0x%x"), hr);
return hr ;
}
SAFE_RELEASE(pContext);
SAFE_RELEASE(pBaseFilter);
return hr;
}
HRESULT CCaptureVideo::FindCaptureDeviceMoniker(IMoniker **ppMoniker)
{
HRESULT hr;
ULONG cFetched;
if (!ppMoniker)
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))
{
DisplayMesg(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))
{
DisplayMesg(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)
{
AfxMessageBox("No video capture device was detected.",MB_OK | MB_ICONINFORMATION) ;
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.
/// For finding Digital Capture Devices ...
BOOL Found ;
IPin *pP = 0;
IEnumPins *pins=0;
ULONG n;
PIN_INFO pinInfo;
Found = FALSE;
IKsPropertySet *pKs=0;
GUID guid;
DWORD dw;
BOOL fMatch = FALSE;
IMoniker *pMoniker = NULL;
IBaseFilter *pSrc;
while (S_OK == (pClassEnum->Next (1, ppMoniker, &cFetched)))
{
pMoniker = ppMoniker[0];
hr = pMoniker->BindToObject(0,0,IID_IBaseFilter, (void**)&pSrc);
if (FAILED(hr))
{
DisplayMesg(TEXT("Couldn't bind moniker to filter object! hr=0x%x"), hr);
return hr;
}
else
pSrcF = pSrc;
if(SUCCEEDED(pSrc->EnumPins(&pins)))
{
while(!Found && (S_OK == pins->Next(1, &pP, &n)))
{
if(S_OK == pP->QueryPinInfo(&pinInfo))
{
if(pinInfo.dir == PINDIR_INPUT)
{
// is this pin an ANALOGVIDEOIN input pin?
if(pP->QueryInterface(IID_IKsPropertySet,
(void **)&pKs) == S_OK)
{
if(pKs->Get(AMPROPSETID_Pin,
AMPROPERTY_PIN_CATEGORY, NULL, 0,
&guid, sizeof(GUID), &dw) == S_OK)
{
if(guid == PIN_CATEGORY_ANALOGVIDEOIN)
fMatch = TRUE;
}
pKs->Release();
}
if(fMatch)
{
Found = TRUE;
bDevCheck = Found;
nAnalogCount++;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -