// Get DirectShow interfaces
hr = GetInterfaces();
if (FAILED(hr))
{
Msg(TEXT("Failed to get video interfaces! hr=0x%x"), hr);
return hr;
}
// Attach the filter graph to the capture graph
hr = g_pCapture->SetFiltergraph(g_pGraph);
if (FAILED(hr))
{
Msg(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;
}
// Add Capture filter to our graph.
hr = g_pGraph->AddFilter(pSrcFilter, L"Video Capture");
if (FAILED(hr))
{
Msg(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);
pSrcFilter->Release();
return hr;
}
// Render the preview pin on the video capture filter
// Use this instead of g_pGraph->RenderFile
hr = g_pCapture->RenderStream (&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
pSrcFilter, NULL, NULL);
if (FAILED(hr))
{
Msg(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;
}
// 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))
{
Msg(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(g_pGraph, &g_dwGraphRegister);
if (FAILED(hr))
{
Msg(TEXT("Failed to register filter graph with ROT! hr=0x%x"), hr);
g_dwGraphRegister = 0;
}
#endif
// Start previewing video data
hr = g_pMC->Run();
if (FAILED(hr))
{
Msg(TEXT("Couldn't run the graph! hr=0x%x"), hr);
return hr;
}
while(SUCCEEDED(g_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 = g_pME->FreeEventParams(evCode, evParam1, evParam2);
// Insert event processing code here, if desired
}
接上条:
void TForm1::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
// Create an enumerator for the video capture devices
CComPtr <IEnumMoniker> pClassEnum = NULL;
hr = pDevEnum->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &pClassEnum, 0);
if (FAILED(hr))
{
Msg(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(Handle,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.
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))
{
Msg(TEXT("Couldn't bind moniker to filter object! hr=0x%x"), hr);
return hr;
}
}
else
{
Msg(TEXT("Unable to access video capture device!"));
return E_FAIL;
}
// Copy the found filter pointer to the output parameter.
// Do NOT Release() the reference, since it will still be used
// by the calling function.
*ppSrcFilter = pSrc;
return hr;
}
//---------------------------------------------------------------------------
void TForm1::ResizeVideoWindow(void)
{
// Resize the video preview window to match owner window size
if (g_pVW)
{
RECT rc;
// Make the preview video fill our window
::GetClientRect(Handle, &rc);
g_pVW->SetWindowPosition(0, 0, rc.right, rc.bottom);
}
}
//---------------------------------------------------------------------------
HRESULT TForm1::SetupVideoWindow(void)
{
HRESULT hr;
// Set the video window to be a child of the main window
hr = g_pVW->put_Owner((OAHWND)Handle);
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();
// Make the video window visible, now that it is properly positioned
hr = g_pVW->put_Visible(OATRUE);
if (FAILED(hr))
return hr;
case WM_WINDOWPOSCHANGED:
ChangePreviewState(!(IsIconic(Handle)));
break;
case WM_CLOSE:
// Hide the main window while the graph is destroyed
ShowWindow(Handle, SW_HIDE);
CloseInterfaces(); // Stop capturing and release interfaces
break;
case WM_DESTROY:
PostQuitMessage(0);
Message.Result = 0;
return;
}
// Pass this message to the video window for notification of system changes
if (g_pVW)
g_pVW->NotifyOwnerMessage((LONG_PTR)Handle, Message.Msg, Message.WParam, Message.LParam);
TForm::WndProc(Message);
}
//---------------------------------------------------------------------------
void TForm1::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);