📄 capturevideo.cpp
字号:
// CaptureVideo.cpp : implementation file
//
//--------------------------------------------------------------------------//
// Copyright DILLIP KUMAR KARA 2004
// You may do whatever you want with this code, as long as you include this
// copyright notice in your implementation files.
// Comments and bug Reports: codeguru_bank@yahoo.com
//--------------------------------------------------------------------------//
#include "stdafx.h"
#include "LiveVideo.h"
#include "CaptureVideo.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
HRESULT SaveGraphFile(IGraphBuilder *pGraph, WCHAR *wszPath) ;
IPin *GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir);
HRESULT ConnectAudio(IAMCrossbar *pXBar, BOOL bActivate);
/////////////////////////////////////////////////////////////////////////////
// CCaptureVideo
CCaptureVideo::CCaptureVideo()
{
// Initialization
m_hApp=NULL;
m_dwGraphRegister=0;
nAnalogCount =0; // Counting Analog devices
m_pVW = NULL;
m_pMC = NULL;
m_pME = NULL;
m_pGraph = NULL; // IFilterGraph2 provides AddSourceFileForMoniker()
m_pCapture = NULL;
pSrcF = NULL ;
/// For Webcam
m_pVWMoniker = NULL;
m_pMCMoniker = NULL;
m_pMEMoniker = NULL;
m_pCaptureMoniker = NULL;
m_pFilterGraph = NULL;
}
CCaptureVideo::~CCaptureVideo()
{
}
BEGIN_MESSAGE_MAP(CCaptureVideo, CWnd)
//{{AFX_MSG_MAP(CCaptureVideo)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
ON_MESSAGE(WM_GRAPHNOTIFY, OnGraphNotify)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCaptureVideo message handlers
HRESULT CCaptureVideo::InitializeVideo(HWND hWnd)
{
HRESULT hr = NULL ;
m_hApp = hWnd ;
bDevCheck = FALSE;
nVSourceCount =0;
vType = 0;
//COM Library Intialization
if(FAILED(CoInitialize(NULL))) /*, COINIT_APARTMENTTHREADED)))*/
{
AfxMessageBox("CoInitialize Failed!\r\n");
return hr ;
}
return hr ;
}
void CCaptureVideo::UnIntializeVideo()
{
if( vType == 1) // If WebCam
CloseInterfacesMoniker();
CloseInterfaces();
CoUninitialize();
bVideo = FALSE;
}
HRESULT CCaptureVideo::GetInterfaces()
{
HRESULT hr;
if(m_pGraph == NULL){
// Create the filter graph
hr = CoCreateInstance (CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **) &m_pGraph);
if (FAILED(hr))
return hr;
}
else
return E_FAIL ;
if(m_pCapture == NULL) {
// Create the capture graph builder
hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,
IID_ICaptureGraphBuilder2, (void **) &m_pCapture);
if (FAILED(hr))
return hr;
}
else
return E_FAIL ;
// Obtain interfaces for media control and Video Window
hr = m_pGraph->QueryInterface(IID_IMediaControl,(LPVOID *) &m_pMC);
if (FAILED(hr))
return hr;
hr = m_pGraph->QueryInterface(IID_IVideoWindow, (LPVOID *) &m_pVW);
if (FAILED(hr))
return hr;
hr = m_pGraph->QueryInterface(IID_IMediaEvent, (LPVOID *) &m_pME);
if (FAILED(hr))
return hr;
// Set the window handle used to process graph events
hr = m_pME->SetNotifyWindow((OAHWND)m_hApp, WM_GRAPHNOTIFY, 0);
return hr;
}
HRESULT CCaptureVideo::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))
{
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)
{
// MessageBox(m_hApp,TEXT("No video capture device was detected.\r\n\r\n")
// TEXT("This sample requires a video capture device, such as a USB WebCam,\r\n")
// TEXT("to be installed and working properly. The sample will now close."),
// TEXT("No Video Capture Hardware"), 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.
//To Find the Analog 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;
//while(S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched)))
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))
{
DisplayMesg(TEXT("Couldn't bind moniker to filter object! hr=0x%x"), hr);
return hr;
}
if(SUCCEEDED(pSrc->EnumPins(&pins)))
{
while(!Found && (S_OK == pins->Next(1, &pP, &n)))
{
vType ++;
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;
break;
}
}
pinInfo.pFilter->Release();
}
pP->Release();
}
pins->Release();
}
}
// Copy the found filter pointer to the output parameter.
// Do NOT Release() the reference, since it will still be used
// by the calling function.
pSrcF = pSrc;
*ppSrcFilter = pSrc;
return hr;
}
// @@@@@@@@@@@
HRESULT CCaptureVideo::FindCaptureDeviceAudio(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))
{
DisplayMesg(TEXT("Couldn't create system enumerator! hr=0x%x"), hr);
return hr;
}
// Create an enumerator for the @Audio@ capture devices
CComPtr <IEnumMoniker> pClassEnum = NULL;
hr = pDevEnum->CreateClassEnumerator (CLSID_AudioInputDeviceCategory/*CLSID_VideoInputDeviceCategory*/, &pClassEnum, 0);
if (FAILED(hr))
{
DisplayMesg(TEXT("Couldn't create class enumerator! hr=0x%x"), hr);
return hr;
}
pClassEnum->Reset();
// If there are no enumerators for the requested type, then
// CreateClassEnumerator will succeed, but pClassEnum will be NULL.
if (pClassEnum == NULL)
{
// MessageBox(m_hApp,TEXT("No video capture device was detected.\r\n\r\n")
// TEXT("This sample requires a video capture device, such as a USB WebCam,\r\n")
// TEXT("to be installed and working properly. The sample will now close."),
// TEXT("No Video Capture Hardware"), 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.
//To Find the Analog 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;
//while(S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched)))
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))
{
DisplayMesg(TEXT("Couldn't bind moniker to filter object! hr=0x%x"), hr);
return hr;
}
if(SUCCEEDED(pSrc->EnumPins(&pins)))
{
while(!Found && (S_OK == pins->Next(1, &pP, &n)))
{
vType ++;
if(S_OK == pP->QueryPinInfo(&pinInfo))
{
TRACE(CString("Name : ")+ pinInfo.achName );
TRACE1(" DIR : %d" , pinInfo.dir);
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;
break;
}
}
pinInfo.pFilter->Release();
}
pP->Release();
}
pins->Release();
}
}
// Copy the found filter pointer to the output parameter.
// Do NOT Release() the reference, since it will still be used
// by the calling function.
pSrcF = pSrc;
*ppSrcFilter = pSrc;
return hr;
}
HRESULT CCaptureVideo::SetupVideoWindow()
{
HRESULT hr;
// Set the video window to be a child of the main window
hr = m_pVW->put_Owner((OAHWND)m_hApp);
if (FAILED(hr))
return hr;
// Set video window style
hr = m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);
if (FAILED(hr))
return hr;
hr = m_pVW->put_Width(320) ;
hr = m_pVW->put_Height(240) ;
// Use helper function to position video window in client rect
// of main application window
ResizeVideoWindow();
// Make the video window visible, now that it is properly positioned
hr = m_pVW->put_Visible(OATRUE);
if (FAILED(hr))
return hr;
hr = m_pVW->put_MessageDrain((OAHWND)m_hApp);
return hr;
}
HRESULT CCaptureVideo::ChangePreviewState(int nShow)
{
HRESULT hr=S_OK;
// If the media control interface isn't ready, don't call it
if (!m_pMC)
return S_OK;
if (nShow)
{
if (m_psCurrent != RUNNING)
{
// Start previewing video data
hr = m_pMC->Run();
m_psCurrent = RUNNING;
}
}
else
{
// Stop previewing video data
hr = m_pMC->StopWhenReady();
m_psCurrent = STOPPED;
}
return hr;
}
HRESULT CCaptureVideo::HandleGraphEvent()
{
LONG evCode, evParam1, evParam2;
HRESULT hr=S_OK;
if (!m_pME)
return E_POINTER;
while(SUCCEEDED(m_pME->GetEvent(&evCode, (LONG_PTR *) &evParam1,
(LONG_PTR *) &evParam2, 0)))
{
//
// Free event parameters to prevent memory leaks associated with
// event parameter data. While this application is not interested
// in the received events, applications should always process them.
//
hr = m_pME->FreeEventParams(evCode, evParam1, evParam2);
}
return hr;
}
HRESULT CCaptureVideo::CaptureVideo()
{
HRESULT hr;
IBaseFilter *pSrcFilter=NULL;
IBaseFilter *pSrcAudioFilter=NULL;
// Get DirectShow interfaces
hr = GetInterfaces();
if (FAILED(hr))
{
DisplayMesg(TEXT("Failed to get video interfaces! hr=0x%x"), hr);
return hr;
}
// Attach the filter graph to the capture graph
hr = m_pCapture->SetFiltergraph(m_pGraph);
if (FAILED(hr))
{
DisplayMesg(TEXT("Failed to set capture filter graph! hr=0x%x"), hr);
return hr;
}
// Use the system device enumerator and class enumerator to find
// a video capture/preview device, such as a desktop USB video camera.
hr = FindCaptureDevice(&pSrcFilter);
if (FAILED(hr))
{
// Don't display a message because FindCaptureDevice will handle it
return hr;
}
// @@@@
//hr = FindCaptureDeviceAudio(&pSrcAudioFilter);
// if (FAILED(hr))
// {
// return hr;
//}
if(nAnalogCount == 0)
AfxMessageBox("Capture device is not detected.!") ;
if( bDevCheck == FALSE)
{
return E_FAIL;
}
// Add Capture filter to our graph.
hr = m_pGraph->AddFilter(pSrcFilter, L"Video 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);
pSrcFilter->Release();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -