www.pudn.com > mputil.rar > MPDirectShow.cpp


/*  
 *  MPDirectShow.cpp 
 * 
 *  Created by Bret Fortenberry June 2004. 
 *  Fixes:  
 *  
 *  Copyright (c) 2004 Machine Perception Laboratory  
 *  University of California San Diego. 
 *  
 * Please read the disclaimer and notes about redistribution  
 * at the end of this file. 
 *   
 */ 
 
#include  
#include  
#include  
#include  
#include  
#include "MPDirectShow.h" 
#include "MPUFilter_uids.h" 
 
#define MAX_LOADSTRING 100 
#define FRAMERATE		30 
 
/*#define JIF(x) if (FAILED(hr=(x))) \ 
    { MessageBox(NULL, m_ErrMsg.GetBuffer(0), NULL, MB_OK); \ 
	  m_ErrMsg = oldErr; \ 
	  return hr;}*/ 
#define JIF(x) if (FAILED(hr=(x))) \ 
    MessageBox(NULL, "failed",NULL,MB_OK);   
#define JIF_NRTN(x) if (FAILED(hr=(x))) \ 
      MessageBox(NULL, "failed",NULL,MB_OK);  
 
 
MPDirectShow::MPDirectShow() 
{ 
    HRESULT hr; 
 
	//m_ErrMsg = "Could not initilize DirectShow"; 
 
	pGraph = NULL; 
	pBuild = NULL; 
	m_width = 320; 
	m_height = 240; 
	m_usingCompressor = FALSE; 
	m_curProject = ds_mpisearch; 
	m_recordMode = ds_stop; 
	JIF_NRTN(CoInitialize(NULL)); 
 
	JIF(CoCreateInstance (CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **) &pGraph)); 
	JIF(CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **)&pBuild)); 
	JIF(pBuild->SetFiltergraph(pGraph)); 
 
//	m_ErrMsg = "Running MPDirectShow"; 
} 
 
MPDirectShow::~MPDirectShow() 
{ 
	pControl->Stop(); 
	pEvent.Release(); 
	pWindow.Release(); 
	pControl.Release(); 
	if(pGraph) pGraph->Release(); 
	pBuild->Release(); 
} 
 
void MPDirectShow::SetProject(ds_project curProject) 
{ 
	m_curProject = curProject; 
} 
 
void MPDirectShow::SetInput(int width, int height) 
{ 
	m_width = width; 
	m_height = height; 
} 
 
 
HRESULT MPDirectShow::FindAllDevices( REFCLSID clsidDeviceClass, int* totalFound) 
{ 
    HRESULT hr; 
	//CString oldErr = m_ErrMsg; 
	//m_ErrMsg = "Error Finding Devices"; 
 
    // create an enumerator 
    // 
    CComPtr< ICreateDevEnum > pCreateDevEnum; 
    JIF(pCreateDevEnum.CoCreateInstance( CLSID_SystemDeviceEnum )); 
    if( !pCreateDevEnum ) 
        return hr; 
 
    // enumerate video capture devices 
    // 
    CComPtr< IEnumMoniker > pEm; 
	JIF_NRTN(pCreateDevEnum->CreateClassEnumerator( clsidDeviceClass, &pEm, 0 )); 
    if( !pEm )   {pCreateDevEnum.Release(); return hr;} 
 
    pEm->Reset( ); 
 
    // go through and find first video capture device 
    // 
    CComPtr< IMoniker > pM; 
    for( int i = 0; ; i++) 
    { 
//		m_ErrMsg = "No Compressors found"; 
        ULONG ulFetched = 0; 
 
        JIF_NRTN(pEm->Next( 1, &pM, &ulFetched )); 
        if( hr != S_OK ) { 
			*totalFound = i; 
			break; 
		} 
 
        // get the property bag interface from the moniker 
        // 
        CComPtr< IPropertyBag > pBag; 
        hr = pM->BindToStorage( 0, 0, IID_IPropertyBag, (void**) &pBag ); 
        if( hr != S_OK ) 
			continue;  
 
        // ask for the english-readable name 
        // 
        CComVariant var; 
        var.vt = VT_BSTR; 
        hr = pBag->Read( L"FriendlyName", &var, NULL );  
        if( hr != S_OK ) 
			continue; 
 
        // set it in our UI 
        // 
        USES_CONVERSION; 
		char szName[256]; 
 
		WideCharToMultiByte(CP_ACP,0,var.bstrVal,-1,szName,256,0,0); 
		strcpy(m_deviceNames[i], szName); 
		//MessageBox(NULL,szName, "Compressor name", MB_OK); 
    } 
 
	pCreateDevEnum.Release(); 
	pEm.Release(); 
 
	//m_ErrMsg = oldErr; 
    return hr; 
} 
 
// ================================================================ 
 
HRESULT MPDirectShow::GetDefaultCapDevice( IBaseFilter ** ppCap, REFCLSID clsidDeviceClass ) 
{ 
    HRESULT hr; 
	//CString oldErr = m_ErrMsg; 
	//m_ErrMsg = "Error Loading Camera"; 
 
    *ppCap = NULL; 
 
    // create an enumerator 
    // 
    CComPtr< ICreateDevEnum > pCreateDevEnum; 
    JIF(pCreateDevEnum.CoCreateInstance( CLSID_SystemDeviceEnum )); 
    if( !pCreateDevEnum ) 
        return hr; 
 
    // enumerate video capture devices 
    // 
    CComPtr< IEnumMoniker > pEm; 
	JIF_NRTN(pCreateDevEnum->CreateClassEnumerator( clsidDeviceClass, &pEm, 0 )); 
    if( !pEm )   {pCreateDevEnum.Release(); return hr;} 
 
    pEm->Reset( ); 
 
    // go through and find first video capture device 
    // 
    CComPtr< IMoniker > pM; 
    while( 1 ) 
    { 
//		m_ErrMsg = "No Cameras Connected"; 
        ULONG ulFetched = 0; 
 
        JIF_NRTN(pEm->Next( 1, &pM, &ulFetched )); 
        if( hr != S_OK ) break; 
 
        // get the property bag interface from the moniker 
        // 
        CComPtr< IPropertyBag > pBag; 
        hr = pM->BindToStorage( 0, 0, IID_IPropertyBag, (void**) &pBag ); 
        if( hr != S_OK ) 
			continue;  
 
        // ask for the english-readable name 
        // 
        CComVariant var; 
        var.vt = VT_BSTR; 
        hr = pBag->Read( L"FriendlyName", &var, NULL ); 
        if( hr != S_OK ) 
			continue; 
 
        // set it in our UI 
        // 
        USES_CONVERSION; 
        //SetDlgItemText( IDC_CAPOBJ, W2T( var.bstrVal ) ); 
 
        // ask for the actual filter 
        // 
        hr = pM->BindToObject( 0, 0, IID_IBaseFilter, (void**) ppCap ); 
        if( *ppCap ) break; 
    } 
 
	pCreateDevEnum.Release(); 
	pEm.Release(); 
 
	//m_ErrMsg = oldErr; 
    return hr; 
} 
 
// ================================================================ 
 
HRESULT MPDirectShow::GetListedDevice( IBaseFilter ** ppCom, REFCLSID clsidDeviceClass, char* deviceName) 
{ 
    HRESULT hr; 
	//CString oldErr = m_ErrMsg; 
	//m_ErrMsg = "Error Loading Device"; 
 
    *ppCom = NULL; 
 
    // create an enumerator 
    // 
    CComPtr< ICreateDevEnum > pCreateDevEnum; 
    JIF(pCreateDevEnum.CoCreateInstance( CLSID_SystemDeviceEnum )); 
    if( !pCreateDevEnum ) 
        return hr; 
 
    // enumerate video capture devices 
    // 
    CComPtr< IEnumMoniker > pEm; 
	JIF_NRTN(pCreateDevEnum->CreateClassEnumerator( clsidDeviceClass, &pEm, 0 )); 
    if( !pEm )   {pCreateDevEnum.Release(); return hr;} 
 
    pEm->Reset( ); 
 
    // go through and find first video capture device 
    // 
    CComPtr< IMoniker > pM; 
    while( 1 ) 
    { 
//		m_ErrMsg = "No Devices found"; 
        ULONG ulFetched = 0; 
 
        JIF_NRTN(pEm->Next( 1, &pM, &ulFetched )); 
        if( hr != S_OK ) { 
			pCreateDevEnum.Release(); 
			pEm.Release(); 
			JIF(E_FAIL); 
		} 
 
        // get the property bag interface from the moniker 
        // 
        CComPtr< IPropertyBag > pBag; 
        hr = pM->BindToStorage( 0, 0, IID_IPropertyBag, (void**) &pBag ); 
        if( hr != S_OK ) 
			continue;  
 
        // ask for the english-readable name 
        // 
        CComVariant var; 
        var.vt = VT_BSTR; 
        hr = pBag->Read( L"FriendlyName", &var, NULL ); 
        if( hr != S_OK ) 
			continue; 
 
        // set it in our UI 
        // 
        USES_CONVERSION; 
		char szName[256]; 
 
		WideCharToMultiByte(CP_ACP,0,var.bstrVal,-1,szName,256,0,0); 
		//MessageBox(NULL,szName, "Compressor name", MB_OK); 
 
        // ask for the actual filter 
        // 
		if(!strcmp(szName, deviceName))  
		{ 
			WideCharToMultiByte(CP_ACP,0,var.bstrVal,-1,szName,256,0,0); 
			//MessageBox(NULL,szName, "Device Found", MB_OK); 
			hr = pM->BindToObject( 0, 0, IID_IBaseFilter, (void**) ppCom ); 
			if( *ppCom ) break; 
			else { 
				pCreateDevEnum.Release(); 
				pEm.Release(); 
				JIF(E_FAIL); 
			} 
		} 
    } 
 
	pCreateDevEnum.Release(); 
	pEm.Release(); 
 
	//m_ErrMsg = oldErr; 
    return hr; 
} 
 
// ================================================================ 
 
HRESULT MPDirectShow::RunDirectShow(HWND hWnd) 
{ 
	HRESULT hr; 
//	CString oldErr = m_ErrMsg; 
//	m_ErrMsg = "MPDirectShow::RunDirectShow"; 
 
	//obtain a pointer to the MediaControl 
	pControl = pGraph; 
	pWindow = pGraph; 
 
	// Build the graph manually 
	JIF(CreateManualGraph(hWnd)); 
 
 
	SetDisplayWnd(hWnd); 
 
	// run the graph 
	pEvent = pGraph; 
	JIF(pEvent->SetNotifyWindow(NULL, 0, 0)); 
 
	JIF(pControl->Run()); 
 
	//SaveVideo(); 
//	m_ErrMsg = oldErr; 
	return hr; 
} 
 
// ================================================================ 
 
HRESULT MPDirectShow::CreateManualGraph(HWND hWnd) 
{ 
 
	HRESULT hr; 
//	CString oldErr = m_ErrMsg; 
//	m_ErrMsg = "Error Creating Graph"; 
 
	/////////////// Add All Filters to the Graph /////////////////////////// 
	// Capture device 
	CComPtr< IBaseFilter > pVideoCap; 
 
	if(FAILED(pGraph->FindFilterByName(L"Video Camera", &pVideoCap))) 
			GetDefaultCapDevice( &pVideoCap, CLSID_VideoInputDeviceCategory ); 
	JIF(pGraph->AddFilter( pVideoCap, L"Video Camera" )); 
 
	// Avi decompressor 
	CComPtr< IBaseFilter > pAVIDecompressor; 
	JIF(pAVIDecompressor.CoCreateInstance( CLSID_AVIDec )); 
	JIF(pGraph->AddFilter(pAVIDecompressor, L"AVI Decompressor")); 
 
	// MPLab Filter for running processes 
	// Add any new filter to the list of struct **enum is defined in MPDirectShow.h 
	CComPtr< IBaseFilter > pFaceFinder; 
	switch (m_curProject) { 
	case ds_mpisearch: 
		if (FAILED(hr = pFaceFinder.CoCreateInstance( CLSID_MPISearchFilter ))) 
		{ 
			MessageBox(NULL, (LPCTSTR)"The mpisearch filter is not registered", NULL, MB_OK);  
			exit (-1); 
		} 
		break; 
	case ds_eyefinder: 
		if (FAILED(hr = pFaceFinder.CoCreateInstance( CLSID_MPEyeFinderFilter ))) 
		{ 
			MessageBox(NULL, (LPCTSTR)"The EyeFinder filter is not registered", NULL, MB_OK);  
			exit (-1); 
		} 
		break; 
	case ds_colorTracker: 
		if (FAILED(hr = pFaceFinder.CoCreateInstance( CLSID_MPColorTrackerFilter ))) 
		{ 
			MessageBox(NULL, (LPCTSTR)"The ColorTracker filter is not registered", NULL, MB_OK);  
			exit (-1); 
		} 
		break; 
	case ds_blinkDetector: 
		if (FAILED(hr = pFaceFinder.CoCreateInstance( CLSID_MPBlinkDetectorFilter ))) 
		{ 
			MessageBox(NULL, (LPCTSTR)"The BlinkDetector filter is not registered", NULL, MB_OK);  
			exit (-1); 
		} 
		break; 
	case ds_mpisearchAda: 
		if (FAILED(hr = pFaceFinder.CoCreateInstance( CLSID_MPISearchAdaFilter ))) 
		{ 
			MessageBox(NULL, (LPCTSTR)"The mpisearch AdaBoost filter is not registered", NULL, MB_OK);  
			exit (-1); 
		} 
		break; 
	case ds_emoMirror: 
		if (FAILED(hr = pFaceFinder.CoCreateInstance( CLSID_EmoMirror ))) 
		{ 
			MessageBox(NULL, (LPCTSTR)"The mpisearch AdaBoost filter is not registered", NULL, MB_OK);  
			exit (-1); 
		} 
		break; 
	}; 
	JIF(pGraph->AddFilter(pFaceFinder, L"MPFilter")); 
 
	// Smart Tee 
	CComPtr< IBaseFilter > pSmartTee; 
	JIF(pSmartTee.CoCreateInstance( CLSID_SmartTee )); 
	JIF(pGraph->AddFilter(pSmartTee, L"Smart Tee")); 
 
 
	///////////// Set video input properties /////////////  
	CComQIPtr< IPin > pOutPin; 
	CComQIPtr< IPin > pInPin; 
 
	//get video dimensions 
	JIF(GetPin(pVideoCap, PINDIR_OUTPUT, &pOutPin)); 
	JIF(GetPin(pAVIDecompressor, PINDIR_INPUT, &pInPin)); 
 
	CComQIPtr< IAMStreamConfig > pStreamConfig; 
	pStreamConfig = pOutPin; 
	AM_MEDIA_TYPE *pmt = NULL; 
 
	JIF(GetMediaType(pOutPin, pInPin, pmt)); 
	JIF(pStreamConfig->SetFormat(pmt)); 
	JIF(pStreamConfig->GetFormat(&pmt)); 
 
	VIDEOINFOHEADER* vih = (VIDEOINFOHEADER *) pmt->pbFormat; 
	long lWidth  = vih->bmiHeader.biWidth; 
	long lHeight = vih->bmiHeader.biHeight; 
	lWidth = m_width; 
	lHeight = m_height; 
	vih->bmiHeader.biWidth = lWidth; 
  vih->bmiHeader.biHeight = lHeight; 
 
	vih->AvgTimePerFrame = (LONGLONG) 10000000/FRAMERATE; 
 
	// Create video input interface 
	ISpecifyPropertyPages *pProp; 
	JIF(pVideoCap->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pProp)); 
	//if (SUCCEEDED(hr)) 
	{ 
			// Get the filter's name and IUnknown pointer. 
			FILTER_INFO FilterInfo; 
			hr = pVideoCap->QueryFilterInfo(&FilterInfo); 
			IUnknown *pFilterUnk; 
			pVideoCap->QueryInterface(IID_IUnknown, (void **)&pFilterUnk); 
 
			// Show the page. 
			CAUUID caGUID; 
			pProp->GetPages(&caGUID); 
			pProp->Release(); 
			OleCreatePropertyFrame( 
					hWnd,                   // Parent window 
					0, 0,                   // Reserved 
					FilterInfo.achName,     // Caption for the dialog box 
					1,                      // Number of objects (just the filter) 
					&pFilterUnk,            // Array of object pointers. 
					caGUID.cElems,          // Number of property pages 
					caGUID.pElems,          // Array of property page CLSIDs 
					0,                      // Locale identifier 
					0, NULL                 // Reserved 
			); 
 
			// Clean up. 
			pFilterUnk->Release(); 
			FilterInfo.pGraph->Release(); 
			CoTaskMemFree(caGUID.pElems); 
	} 
 
	 
	//////////////////// Connect Graph /////////////////////////  
	//  videoCapture -> aviDecompressor -> MPLabFilter  
	JIF(ConnectFilters(pVideoCap, pAVIDecompressor)); 
	JIF(ConnectFilters(pAVIDecompressor,pFaceFinder)); 
	JIF(ConnectFilters(pFaceFinder,pSmartTee)); 
 
 
	//////////////////// Render Graph //////////////////////// 
	pOutPin.Release(); 
	GetPin_Name(pSmartTee, "Preview", &pOutPin); 
	pGraph->Render(pOutPin); 
 
	//////// Release all temparary devices (clean up) //////////// 
	// input stream devices 
	pOutPin.Release(); 
	pInPin.Release(); 
	pStreamConfig.Release(); 
	// graph devices 
	pVideoCap.Release(); 
	pAVIDecompressor.Release(); 
	pFaceFinder.Release(); 
	pSmartTee.Release(); 
	 
//	m_ErrMsg = oldErr; 
	return hr; 
 
} 
 
// ================================================================ 
 
HRESULT MPDirectShow::SetDisplayWnd(HWND hWnd) 
{ 
	HRESULT hr; 
//	CString oldErr = m_ErrMsg; 
//	m_ErrMsg = "Error creating Display Graph"; 
 
	int nTitleHeight = GetSystemMetrics(SM_CYCAPTION); 
	int nBorderWidth = GetSystemMetrics(SM_CXBORDER); 
	int nMenuHeight= GetSystemMetrics(SM_CYMENU); 
 
	int nBorderHeight = GetSystemMetrics(SM_CYBORDER); 
	int screenMult = 3; 
	SetWindowPos(hWnd, NULL, 0, 0, 640 + nBorderWidth, 480 + nTitleHeight + nBorderHeight + nMenuHeight, SWP_NOOWNERZORDER); 
 
	RECT rect; 
	GetClientRect(hWnd,&rect); 
 
	JIF(pWindow->SetWindowPosition(rect.left, rect.top, rect.right, rect.bottom)); 
	JIF(pWindow->put_Owner( (OAHWND) hWnd )) ; 
	JIF(pWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)); 
	//JIF(pWindow->put_Visible(TRUE)); 
 
//	m_ErrMsg = oldErr; 
	return hr; 
 
} 
 
// ================================================================ 
 
HRESULT MPDirectShow::StopCapture() 
{ 
 
	HRESULT hr; 
//	CString oldErr = m_ErrMsg; 
//	m_ErrMsg = "Error trying to stop capture"; 
		 
	JIF(pControl->Stop()); 
 
	CComPtr< IBaseFilter > pAviMux; 
	CComPtr< IBaseFilter > pFileWriter; 
 
	JIF(pGraph->FindFilterByName(L"Mux", &pAviMux)); 
	JIF(pGraph->FindFilterByName(L"File Writer", &pFileWriter)); 
 
	JIF(pGraph->RemoveFilter(pFileWriter)); 
	JIF(pGraph->RemoveFilter(pAviMux)); 
 
	if(m_usingCompressor) { 
		CComPtr< IBaseFilter > pAviCom; 
		JIF(pGraph->FindFilterByName(L"AVI Compressor", &pAviCom)); 
		JIF(pGraph->RemoveFilter(pAviCom)); 
		pAviCom.Release(); 
	} 
 
	JIF(pControl->Run()); 
 
	pAviMux.Release(); 
	pFileWriter.Release(); 
 
	m_recordMode = ds_stop; 
 
//	m_ErrMsg = oldErr; 
	return hr; 
 
} 
 
// ================================================================ 
 
HRESULT MPDirectShow::PauseFilter() 
{ 
	HRESULT hr; 
//	CString oldErr = m_ErrMsg; 
//	m_ErrMsg = "Error trying to pause capture"; 
 
	JIF(pControl->Pause()); 
	m_recordMode = ds_pause; 
 
//	m_ErrMsg = oldErr; 
	return hr; 
} 
 
// ================================================================ 
 
HRESULT MPDirectShow::RunFilter() 
{ 
	HRESULT hr; 
//	CString oldErr = m_ErrMsg; 
//	m_ErrMsg = "Error trying to restart capture"; 
 
	JIF(pControl->Run()); 
	if (m_recordMode == ds_pause) 
		m_recordMode = ds_capture; 
 
//	m_ErrMsg = oldErr; 
	return hr; 
 
} 
 
// ================================================================ 
 
HRESULT MPDirectShow::SaveVideo() 
{ 
	HRESULT hr = 0; 
//	CString oldErr = m_ErrMsg; 
//	m_ErrMsg = "Error trying to start capture"; 
 
	/*JIF(pControl->Stop()); 
 
	CComPtr< IBaseFilter > pAviCom = NULL; 
	CComPtr< IBaseFilter > pAviMux = NULL; 
	CComPtr< IFileSinkFilter > pSink = NULL; 
	CComPtr< IBaseFilter > pSmartTee; 
	CComQIPtr< IPin > pOutPin; 
 
	CFileDialog FileDlg (TRUE, "open file", "", OFN_ENABLESIZING, "AVI |*.avi||"); 
 
	POSITION im; 
	CString pathname; 
	if(FileDlg.DoModal() == IDOK){ 
		im = FileDlg.GetStartPosition(); 
		pathname = FileDlg.GetNextPathName(im); 
	} 
	else 
		return E_FAIL; 
 
	LPWSTR outPath = new WCHAR[256]; 
	int nLen = MultiByteToWideChar(CP_ACP,0,pathname.GetBuffer(pathname.GetLength()),-1,NULL,NULL); 
	MultiByteToWideChar(CP_ACP,0,pathname.GetBuffer(0),-1,outPath,nLen); 
 
	JIF(pBuild->SetOutputFileName(&MEDIASUBTYPE_Avi, outPath, &pAviMux, &pSink));	 
	JIF(pGraph->FindFilterByName(L"Smart Tee", &pSmartTee)); 
 
	JIF(GetPin_Name(pSmartTee, "Capture", &pOutPin)); 
	//Get Compressor if found add it 
 
	int totalDevicesFound; 
	hr = FindAllDevices( CLSID_VideoCompressorCategory, &totalDevicesFound); 
	if(!FAILED(hr)) { 
		DeviceList deviceList; 
		deviceList.setDirectShow(this, totalDevicesFound, dl_compressor); 
		deviceList.DoModal(); 
	} 
 
	hr = pGraph->FindFilterByName(L"AVI Compressor", &pAviCom); 
	if(m_devicePos == totalDevicesFound || FAILED(hr)) { 
		JIF(ConnectFilters(pOutPin, pAviMux)); 
		m_usingCompressor = FALSE; 
	} 
	else  { 
		JIF(pGraph->AddFilter( pAviCom, L"AVI Compressor" )); 
		JIF(ConnectFilters(pOutPin, pAviCom)); 
		JIF(ConnectFilters(pAviCom, pAviMux)); 
		m_usingCompressor = TRUE; 
	} 
 
	m_recordMode = ds_capture; 
 
	pSink.Release(); 
	pAviMux.Release(); 
	pSmartTee.Release(); 
	pOutPin.Release(); 
	pAviCom.Release(); 
 
	JIF(pControl->Run()); 
*/ 
//	m_ErrMsg = oldErr; 
	return hr; 
} 
 
// ================================================================ 
 
HRESULT MPDirectShow::ChangeMPFilter(HWND hWnd) 
{ 
	HRESULT hr; 
//	CString oldErr = m_ErrMsg; 
//	m_ErrMsg = "Error removing filters"; 
	OAFilterState pf; 
 
	pControl->StopWhenReady(); 
 
	pControl->GetState(100, &pf); 
	if(pf != State_Stopped) 
		return E_FAIL; 
	CComPtr< IBaseFilter > pFaceFinder; 
	CComPtr< IBaseFilter > pVideoRenderer; 
	CComPtr< IBaseFilter > pAVIDecompressor; 
	CComPtr< IBaseFilter > pVideoCap; 
 
	pGraph->FindFilterByName(L"Video Renderer", &pVideoRenderer); 
	pGraph->FindFilterByName(L"MPFilter", &pFaceFinder); 
	pGraph->FindFilterByName(L"AVI Decompressor", &pAVIDecompressor); 
	pGraph->FindFilterByName(L"Video Camera", &pVideoCap); 
 
	hr = pGraph->RemoveFilter(pVideoRenderer); 
	hr = pGraph->RemoveFilter(pFaceFinder); 
	hr = pGraph->RemoveFilter(pAVIDecompressor); 
	hr = pGraph->RemoveFilter(pVideoCap); 
 
	pFaceFinder.Release(); 
	pVideoRenderer.Release(); 
	pAVIDecompressor.Release(); 
	pVideoCap.Release(); 
 
//	m_ErrMsg = oldErr; 
	return hr; 
} 
 
// ================================================================ 
 
// Helper functions: 
HRESULT MPDirectShow::GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin) 
{ 
	IEnumPins  *pEnum; 
	IPin       *pPin; 
	pFilter->EnumPins(&pEnum); 
	while(pEnum->Next(1, &pPin, 0) == S_OK) 
	{ 
		PIN_DIRECTION PinDirThis; 
		pPin->QueryDirection(&PinDirThis); 
		if (PinDir == PinDirThis) 
		{ 
			pEnum->Release(); 
			*ppPin = pPin; 
			return S_OK; 
		} 
		pPin->Release(); 
	} 
	pEnum->Release(); 
	return E_FAIL; 
} 
 
// ================================================================ 
 
// Helper functions: 
HRESULT MPDirectShow::GetPin_Name(IBaseFilter *pFilter, char* name, IPin **ppPin) 
{ 
	IEnumPins  *pEnum; 
	IPin       *pPin; 
	pFilter->EnumPins(&pEnum); 
	while(pEnum->Next(1, &pPin, 0) == S_OK) 
	{ 
		PIN_INFO PinInfo; 
		char szName[256]; 
 
		pPin->QueryPinInfo(&PinInfo); 
		WideCharToMultiByte(CP_ACP,0,PinInfo.achName,-1,szName,256,0,0); 
		if (!strcmp(szName, name)) 
		{ 
			pEnum->Release(); 
			PinInfo.pFilter->Release(); 
			*ppPin = pPin; 
			return S_OK; 
		} 
		pPin->Release(); 
		PinInfo.pFilter->Release(); 
	} 
	pEnum->Release(); 
	return E_FAIL; 
} 
 
// ================================================================ 
 
HRESULT MPDirectShow::ConnectFilters(IBaseFilter *pFirst, IBaseFilter *pSecond) 
{ 
	HRESULT hr; 
//	CString oldErr = m_ErrMsg; 
//	m_ErrMsg = "Error connecting filters"; 
 
	IPin *pOut = NULL, *pIn = NULL; 
	JIF(GetPin(pFirst, PINDIR_OUTPUT, &pOut)); 
	hr = GetPin(pSecond, PINDIR_INPUT, &pIn); 
	if (FAILED(hr)) 
	{ 
		pOut->Release(); 
		JIF(hr); 
	} 
	JIF(pGraph->Connect(pOut, pIn)); 
	pIn->Release(); 
	pOut->Release(); 
 
//	m_ErrMsg = oldErr; 
	return hr; 
} 
 
// ================================================================ 
 
HRESULT MPDirectShow::ConnectFilters(IPin *pOut, IBaseFilter *pSecond) 
{ 
	HRESULT hr; 
//	CString oldErr = m_ErrMsg; 
//	m_ErrMsg = "Error connecting filters"; 
 
	IPin *pIn = NULL; 
	JIF(GetPin(pSecond, PINDIR_INPUT, &pIn)); 
 
	JIF(pGraph->Connect(pOut, pIn)); 
	pIn->Release(); 
 
//	m_ErrMsg = oldErr; 
	return hr; 
} 
 
// ================================================================ 
 
HRESULT MPDirectShow::DisonnectFilters(IBaseFilter *pFilter, PIN_DIRECTION pindir) 
{ 
	HRESULT hr; 
//	CString oldErr = m_ErrMsg; 
//	m_ErrMsg = "Error disconnecting filters"; 
 
	IPin *pin = NULL; 
	JIF(GetPin(pFilter, pindir, &pin)); 
	JIF(pGraph->Disconnect(pin)); 
	pin->Release(); 
 
//	m_ErrMsg = oldErr; 
	return hr; 
} 
 
// ================================================================ 
 
void MPDirectShow::EnumFilters(void) 
{ 
	IEnumFilters *pEnum = NULL; 
	IBaseFilter *pFilter; 
	ULONG cFetched; 
 
	pGraph->EnumFilters(&pEnum); 
	while(pEnum->Next(1,&pFilter,&cFetched) == S_OK) 
	{ 
		FILTER_INFO FilterInfo; 
		char szName[256]; 
 
		pFilter->QueryFilterInfo(&FilterInfo); 
		WideCharToMultiByte(CP_ACP,0,FilterInfo.achName,-1,szName,256,0,0); 
		MessageBox(NULL,szName, "Filter name", MB_OK); 
		FilterInfo.pGraph->Release(); 
		pFilter->Release(); 
	} 
	pEnum->Release(); 
} 
 
// ================================================================ 
 
void MPDirectShow::EnumPins(IBaseFilter *pFilter) 
{ 
	IEnumPins  *pEnum; 
	IPin       *pPin; 
	pFilter->EnumPins(&pEnum); 
	while(pEnum->Next(1, &pPin, 0) == S_OK) 
	{ 
		PIN_INFO PinInfo; 
		char szName[256]; 
 
		pPin->QueryPinInfo(&PinInfo); 
		WideCharToMultiByte(CP_ACP,0,PinInfo.achName,-1,szName,256,0,0); 
		MessageBox(NULL,szName, "Pin name", MB_OK); 
		PinInfo.pFilter->Release(); 
		pPin->Release(); 
	} 
	pEnum->Release(); 
} 
 
// ================================================================ 
 
// finds the first AM_MEDIA_TYPE from the input pin that correctly connects to the output pin 
HRESULT MPDirectShow::GetMediaType(IPin *outPin, IPin *inPin, AM_MEDIA_TYPE *ppMediaType) 
{ 
	IEnumMediaTypes *ppEnum; 
	HRESULT hr; 
 
	outPin->EnumMediaTypes(&ppEnum); 
	while(ppEnum->Next(1, &ppMediaType, 0) == S_OK) 
	{ 
 
		if((hr = inPin->QueryAccept(ppMediaType)) == S_OK) { 
			ppEnum->Release(); 
			return hr; 
		} 
	} 
	ppEnum->Release(); 
	return hr; 
} 
 
// ================================================================ 
 
HRESULT MPDirectShow::SaveGraphEditFile(WCHAR* wszFileName) 
{ 
    const WCHAR wszStreamName[] = L"ActiveMovieGraph"; 
    HRESULT hr; 
//	CString oldErr = m_ErrMsg; 
//	m_ErrMsg = "Error connecting filters"; 
 
    IStorage *pStorage = NULL; 
    JIF(StgCreateDocfile( 
        wszFileName, 
        STGM_CREATE | STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 
        0, &pStorage)); 
 
    IStream *pStream; 
    hr = pStorage->CreateStream( 
        wszStreamName, 
        STGM_WRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 
        0, 0, &pStream); 
    if (FAILED(hr)) 
    { 
        pStorage->Release(); 
        JIF(hr); 
    } 
 
    CComQIPtr< IPersistStream > pPersist; //IPersistStream *pPersist = NULL; 
    pPersist = pGraph; //pGraph->QueryInterface(IID_IPersistStream, reinterpret_cast(&pPersist)); 
    hr = pPersist->Save(pStream, TRUE); 
    pStream->Release(); 
    pPersist.Release(); //pPersist->Release(); 
    if (SUCCEEDED(hr)) 
    { 
        hr = pStorage->Commit(STGC_DEFAULT); 
    } 
    pStorage->Release(); 
	JIF(hr); 
 
//	m_ErrMsg = oldErr; 
    return hr; 
} 
 
// ================================================================ 
 
int MPDirectShow::GetVideoDevices() { 
	HRESULT hr; 
	int totalDevicesFound; 
 
	hr = FindAllDevices( CLSID_VideoInputDeviceCategory, &totalDevicesFound); 
 
	return totalDevicesFound; 
} 
 
// ================================================================ 
 
void MPDirectShow::SetVideoDevices(int pos) { 
	HRESULT hr; 
	CComPtr< IBaseFilter > pVideoCap; 
 
	GetListedDevice( &pVideoCap, CLSID_VideoInputDeviceCategory, m_deviceNames[pos]); 
	JIF(pGraph->AddFilter( pVideoCap, L"Video Camera" )); 
} 
 
// ================================================================ 
 
/* 
 *  
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 
 *  
 *    1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 
 *    2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 
 *    3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. 
 *  
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 *  
 */