📄 capture.cpp
字号:
if (SUCCEEDED(hr)) {
// Bind Moniker to a filter object
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void **) & pSrc);
if (FAILED(hr)) {
Msg(TEXT("Couldn't bind moniker to filter object! hr=0x%x"), hr);
}
}
// Copy the found filter pointer to the output parameter.
if (SUCCEEDED(hr)) {
*ppSrcFilter = pSrc;
(*ppSrcFilter)->AddRef();
}
SAFE_RELEASE(pSrc);
SAFE_RELEASE(pMoniker);
SAFE_RELEASE(pDevEnum);
SAFE_RELEASE(pClassEnum);
return hr;
}
HRESULT GetInterfaces(HWND hWnd)
{
HRESULT hr;
// Create the filter graph
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **) & g_pGraph);
if (FAILED(hr))
return hr;
// Create the capture graph builder
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,
IID_ICaptureGraphBuilder2, (void **) & g_pCapture);
if (FAILED(hr))
return hr;
// Obtain interfaces for media control and Video Window
hr = g_pGraph->QueryInterface(IID_IMediaControl, (LPVOID *) & g_pMC);
if (FAILED(hr))
return hr;
hr = g_pGraph->QueryInterface(IID_IVideoWindow, (LPVOID *) & g_pVW);
if (FAILED(hr))
return hr;
hr = g_pGraph->QueryInterface(IID_IMediaEvent, (LPVOID *) & g_pME);
if (FAILED(hr))
return hr;
// Set the window handle used to process graph events
hr = g_pME->SetNotifyWindow((OAHWND)hWnd, WM_GRAPHNOTIFY, 0);
return hr;
}
void CloseInterfaces(void)
{
// Stop previewing data
if (g_pMC)
g_pMC->StopWhenReady();
g_psCurrent = Stopped;
// Stop receiving events
if (g_pME)
g_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 (g_pVW) {
g_pVW->put_Visible(OAFALSE);
g_pVW->put_Owner(NULL);
}
#ifdef REGISTER_FILTERGRAPH
// Remove filter graph from the running object table
if (g_dwGraphRegister)
RemoveGraphFromRot(g_dwGraphRegister);
#endif
// Release DirectShow interfaces
SAFE_RELEASE(g_pMC);
SAFE_RELEASE(g_pME);
SAFE_RELEASE(g_pVW);
SAFE_RELEASE(g_pGraph);
SAFE_RELEASE(g_pCapture);
}
HRESULT SetupVideoWindow(HWND hWnd)
{
HRESULT hr;
// Set the video window to be a child of the main window
hr = g_pVW->put_Owner((OAHWND)hWnd);
if (FAILED(hr))
return hr;
// Set video window style
hr = g_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);
if (FAILED(hr))
return hr;
// Use helper function to position video window in client rect
// of main application window
ResizeVideoWindow(hWnd);
// Make the video window visible, now that it is properly positioned
hr = g_pVW->put_Visible(OATRUE);
if (FAILED(hr))
return hr;
return hr;
}
void ResizeVideoWindow(HWND hWnd)
{
// Resize the video preview window to match owner window size
if (g_pVW) {
RECT rc;
// Make the preview video fill our window
GetClientRect(hWnd, &rc);
g_pVW->SetWindowPosition(0, 0, rc.right, rc.bottom);
}
}
HRESULT vcChangePreviewState(int nShow)
{
HRESULT hr = S_OK;
// If the media control interface isn't ready, don't call it
if (!g_pMC)
return S_OK;
if (nShow) {
if (g_psCurrent != Running) {
// Start previewing video data
hr = g_pMC->Run();
g_psCurrent = Running;
}
} else {
// Stop previewing video data
hr = g_pMC->StopWhenReady();
g_psCurrent = Stopped;
}
return hr;
}
#ifdef REGISTER_FILTERGRAPH
HRESULT 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;
hr = StringCchPrintfW(wsz, NUMELMS(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;
}
// Removes a filter graph from the Running Object Table
void RemoveGraphFromRot(DWORD pdwRegister)
{
IRunningObjectTable *pROT;
if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) {
pROT->Revoke(pdwRegister);
pROT->Release();
}
}
#endif
HRESULT vcHandleGraphEvent(void)
{
LONG evCode;
LONG_PTR evParam1, evParam2;
HRESULT hr = S_OK;
if (!g_pME)
return E_POINTER;
while (SUCCEEDED(g_pME->GetEvent(&evCode, &evParam1, &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 = g_pME->FreeEventParams(evCode, evParam1, evParam2);
// Insert event processing code here, if desired
}
return hr;
}
void Msg(TCHAR *szFormat, ...)
{
TCHAR szBuffer[1024]; // Large buffer for long filenames or URLs
const size_t NUMCHARS = sizeof(szBuffer) / sizeof(szBuffer[0]);
const int LASTCHAR = NUMCHARS - 1;
// Format the input string
va_list pArgs;
va_start(pArgs, szFormat);
// Use a bounded buffer size to prevent buffer overruns. Limit count to
// character size minus one to allow for a NULL terminating character.
(void)StringCchVPrintf(szBuffer, NUMCHARS - 1, szFormat, pArgs);
va_end(pArgs);
// Ensure that the formatted string is NULL-terminated
szBuffer[LASTCHAR] = TEXT('\0');
MessageBox(NULL, szBuffer, TEXT("PlayCap Message"), MB_OK | MB_ICONERROR);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -