📄 graphmanager.cpp
字号:
//
// Copyright (c) Microsoft Corporation.� All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include "stdafx.h"
CGraphManager::CGraphManager()
{
m_fGraphBuilt = FALSE;
ZeroMemory( m_handle, sizeof( m_handle ));
m_hwnd = 0;
m_dwThreadId = 0;
m_hThread = NULL;
m_hCommandCompleted = NULL;
m_currentCommand = COMMAND_NOCOMMAND;
}
CGraphManager::~CGraphManager()
{
if( m_handle[0] )
{
CloseHandle( m_handle[0] );
}
if( m_handle[1] )
{
CloseHandle( m_handle[1] );
}
}
HRESULT
CGraphManager::Init()
{
HRESULT hr = S_OK;
// Create the event that will signal the thread for commands
m_handle[0] = CreateEvent( NULL, FALSE, FALSE, NULL );
if( m_handle[0] == NULL )
{
ERR( HRESULT_FROM_WIN32( GetLastError() ));
}
m_handle[1] = 0;
// Create the event to sync on to wait for the command to be executed
m_hCommandCompleted = CreateEvent( NULL, FALSE, FALSE, NULL );
if( m_hCommandCompleted == NULL )
{
ERR( HRESULT_FROM_WIN32( GetLastError() ));
}
// CCreate the thread that will run the filtergraph.
// The filtergraph is runing on a background thread to prevent any window message
// reentrancy issue.
m_hThread = CreateThread( NULL, 0, CGraphManager::ThreadProc, this, 0, &m_dwThreadId );
if( m_hThread == NULL )
{
ERR( HRESULT_FROM_WIN32( GetLastError() ));
}
Cleanup:
return hr;
}
HRESULT
CGraphManager::BuildCaptureGraph()
{
// The Graph is built on a separate thread to
// prevent reentrancy issues.
m_currentCommand = COMMAND_BUILDGRAPH;
SetEvent( m_handle[0] );
WaitForSingleObject( m_hCommandCompleted, INFINITE );
return S_OK;
}
HRESULT
CGraphManager::RunCaptureGraph()
{
// Unlike the other operations, running the graph
// has to happen from the UI thread.
return RunCaptureGraphInternal();
}
HRESULT
CGraphManager::StartRecordVideo()
{
m_currentCommand = COMMAND_STARTCAPTURE;
SetEvent( m_handle[0] );
WaitForSingleObject( m_hCommandCompleted, INFINITE );
return S_OK;
}
HRESULT
CGraphManager::StopRecordVideo()
{
m_currentCommand = COMMAND_STOPCAPTURE;
SetEvent( m_handle[0] );
WaitForSingleObject( m_hCommandCompleted, INFINITE );
return S_OK;
}
HRESULT
CGraphManager::CaptureStillImage()
{
m_currentCommand = COMMAND_STILLIMAGE;
SetEvent( m_handle[0] );
WaitForSingleObject( m_hCommandCompleted, INFINITE );
return S_OK;
}
HRESULT
CGraphManager::ShutDown()
{
m_currentCommand = COMMAND_SHUTDOWN;
SetEvent( m_handle[0] );
WaitForSingleObject( m_hThread, INFINITE );
return S_OK;
}
HRESULT
CGraphManager::RegisterNotificationWindow( HWND hwnd )
{
m_hwnd = hwnd;
return S_OK;
}
DWORD WINAPI
CGraphManager::ThreadProc( LPVOID lpParameter )
{
HRESULT hr = S_OK;
DWORD dwReturnValue;
CGraphManager *pThis = (CGraphManager*) lpParameter;
GRAPHCOMMANDS command = COMMAND_NOCOMMAND;
if( pThis == NULL )
{
return 0;
}
while(( command != COMMAND_SHUTDOWN ) && ( hr != S_FALSE ))
{
dwReturnValue = WaitForMultipleObjects( 2, pThis->m_handle, FALSE, INFINITE );
switch( dwReturnValue )
{
case WAIT_OBJECT_0:
command = pThis->m_currentCommand;
pThis->ProcessCommand();
break;
case WAIT_OBJECT_0 + 1:
pThis->ProcessDShowEvent();
break;
default:
break;
}
};
return 0;
}
HRESULT
CGraphManager::ProcessCommand()
{
HRESULT hr = S_OK;
switch( m_currentCommand )
{
case COMMAND_BUILDGRAPH:
hr = CreateCaptureGraphInternal();
SetEvent( m_hCommandCompleted );
break;
case COMMAND_RUNGRAPH:
hr = RunCaptureGraphInternal();
SetEvent( m_hCommandCompleted );
break;
case COMMAND_STARTCAPTURE:
hr = StartCaptureVideoInternal();
SetEvent( m_hCommandCompleted );
break;
case COMMAND_STOPCAPTURE:
hr = StopCaptureVideoInternal();
SetEvent( m_hCommandCompleted );
break;
case COMMAND_STILLIMAGE:
hr = CaptureStillImageInternal();
SetEvent( m_hCommandCompleted );
break;
case COMMAND_SHUTDOWN:
hr = S_FALSE;
break;
default:
break;
}
return hr;
}
HRESULT
CGraphManager::ProcessDShowEvent()
{
HRESULT hr = S_OK;
long lEventCode, lParam1, lParam2;
CComPtr<IMediaEvent> pMediaEvent;
CComPtr<IGraphBuilder> pFilterGraph;
CComPtr<IMediaControl> pMediaControl;
if( m_pCaptureGraphBuilder == NULL )
{
ERR( E_FAIL );
}
CHK( m_pCaptureGraphBuilder->GetFiltergraph( &pFilterGraph ));
CHK( pFilterGraph->QueryInterface( &pMediaEvent ));
CHK( pMediaEvent->GetEvent( &lEventCode, &lParam1, &lParam2, 0 ));
if( lEventCode == EC_STREAM_CONTROL_STOPPED ) // We have received a control stream stop event
{
NotifyMessage( MESSAGE_ENDRECORDING, L"Recording done ..." );
// To close the file, get the IMediaControl interface, stop and
// restart the graph
CHK( pFilterGraph->QueryInterface( &pMediaControl ));
if( pMediaControl == NULL )
{
ERR( E_POINTER );
}
CHK( pMediaControl->Stop());
CHK( pMediaControl->Run());
NotifyMessage( MESSAGE_FILECAPTURED, L"File captured ..." );
}
else if( lEventCode == EC_CAP_FILE_COMPLETED )
{
NotifyMessage( MESSAGE_FILECAPTURED, L"File captured ..." );
}
CHK( pMediaEvent->FreeEventParams( lEventCode, lParam1, lParam2 ));
Cleanup:
return S_OK;
}
HRESULT
CGraphManager::GetFirstCameraDriver( WCHAR *pwzName )
{
HRESULT hr = S_OK;
HANDLE handle = NULL;
DEVMGR_DEVICE_INFORMATION di;
GUID guidCamera = { 0xCB998A05, 0x122C, 0x4166, 0x84, 0x6A, 0x93, 0x3E, 0x4D, 0x7E, 0x3C, 0x86 };
// Note about the above: The driver material doesn't ship as part of the SDK. This GUID is hardcoded
// here to be able to enumerate the camera drivers and pass the name of the driver to the video capture filter
if( pwzName == NULL )
{
return E_POINTER;
}
di.dwSize = sizeof(di);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -