DirectShow: webcam de prévisualisation et capture d'image

Après avoir regardé une question très semblable et de voir presque à l'identique le code, j'ai décidé de poser cette question séparément. Je veux montrer un aperçu de la vidéo de la webcam du flux vidéo vers la fenêtre par défaut utilise DirectShow, et je veux aussi la possibilité de "prendre une photo" de la diffusion de la vidéo à un moment donné.

J'ai commencé avec le DirectShow exemples sur MSDN, ainsi que la AMCap exemple de code, et qui ont quelque chose à mon avis, devrait l'aperçu de la partie, mais ne le fait pas. Je n'ai trouvé aucun exemple de capture d'une image à partir d'un flux vidéo à l'exception de l'aide SampleGrabber, qui est obsolète et donc j'essaie de ne pas l'utiliser.

Ci-dessous mon code, ligne par ligne. Notez que la plupart du code de EnumerateCameras est commenté. Ce code aurait été pour les attacher à une autre fenêtre, je ne veux pas faire. Dans la documentation MSDN, il est dit explicitement que le VMR_7 crée sa propre fenêtre pour afficher le flux vidéo. Je n'ai pas d'erreurs dans mon application, mais cette fenêtre n'apparaît jamais.

Ma question alors est: est-ce Que je fais mal? Sinon, si vous connaissez un exemple simple de ce que je suis en train de faire, de me lier à lui. AMCap est pas un exemple simple, pour référence.

REMARQUE: InitalizeVMR est pour l'exécution dans la fenêtre de l'état, qui est mon but ultime (l'intégration dans un DirectX jeu). Pour l'instant, cependant, j'ai juste envie de s'exécuter dans le mode le plus simple possible.

EDIT: La première partie de cette question, c'est de la prévisualisation de la caméra de flux, est résolu. Je suis maintenant à la recherche d'une alternative à l'obsolète SampleGrabber classe afin que je puisse prendre une photo à tout moment et d'enregistrer dans un fichier.

EDIT: Après avoir cherché pendant près d'une heure sur google, le consensus général semble être que vous AVEZ à utiliser ISampleGrabber. S'il vous plaît laissez-moi savoir si vous trouvez quelque chose de différent.

Test de code (main.cpp):

CWebcam* camera = new CWebcam();    
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);    
MessageBox(NULL, L"text", L"caption", NULL);    
if (SUCCEEDED(hr))
{       
camera->Create();       
camera->EnumerateCameras();     
camera->StartCamera();  
}   
int d;  
cin >> d;

Webcam.cpp:

#include "Webcam.h"
CWebcam::CWebcam() {
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
//m_pTexInst = nullptr;
//m_pTexRes = nullptr;
}
CWebcam::~CWebcam() {
CoUninitialize();
m_pDeviceMonikers->Release();
m_pMediaController->Release();
}
BOOL CWebcam::Create() {
InitCaptureGraphBuilder(&m_pFilterGraph, &m_pCaptureGraph);
hr = m_pFilterGraph->QueryInterface(IID_IMediaControl, (void **)&m_pMediaController);
return TRUE;
}
void CWebcam::Destroy() {
}
void CWebcam::EnumerateCameras() {  
HRESULT hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &m_pDeviceMonikers);
if (SUCCEEDED(hr))
{
//DisplayDeviceInformation(m_pDeviceMonikers);
//m_pDeviceMonikers->Release();
IMoniker *pMoniker = NULL;
if(m_pDeviceMonikers->Next(1, &pMoniker, NULL) == S_OK)
{
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&m_pCameraFilter);
if (SUCCEEDED(hr))
{
hr = m_pFilterGraph->AddFilter(m_pCameraFilter, L"Capture Filter");
}
}
//connect the output pin to the video renderer
if(SUCCEEDED(hr))
{
hr = m_pCaptureGraph->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, 
m_pCameraFilter, NULL, NULL);
}
//InitializeVMR(hwnd, m_pFilterGraph, &m_pVMRControl, 1, FALSE);
//get the video window that will be displayed from the filter graph
IVideoWindow *pVideoWindow = NULL;
hr = m_pFilterGraph->QueryInterface(IID_IVideoWindow, (void **)&pVideoWindow);
/*if(hr != NOERROR)
{
printf("This graph cannot preview properly");
}
else
{
//get the video stream configurations
hr = m_pCaptureGraph->FindInterface(&PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Video, m_pCameraFilter,
IID_IAMStreamConfig, (void **)&m_pVideoStreamConfig);
//Find out if this is a DV stream
AM_MEDIA_TYPE *pMediaTypeDV;
//fake window handle
HWND window = NULL;
if(m_pVideoStreamConfig && SUCCEEDED(m_pVideoStreamConfig->GetFormat(&pMediaTypeDV)))
{
if(pMediaTypeDV->formattype == FORMAT_DvInfo)
{
//in this case we want to set the size of the parent window to that of
//current DV resolution.
//We get that resolution from the IVideoWindow.
IBasicVideo* pBasivVideo;
//If we got here, gcap.pVW is not NULL 
//ASSERT(pVideoWindow != NULL);
hr = pVideoWindow->QueryInterface(IID_IBasicVideo, (void**)&pBasivVideo);
/*if(SUCCEEDED(hr))
{
HRESULT hr1, hr2;
long lWidth, lHeight;
hr1 = pBasivVideo->get_VideoHeight(&lHeight);
hr2 = pBasivVideo->get_VideoWidth(&lWidth);
if(SUCCEEDED(hr1) && SUCCEEDED(hr2))
{
ResizeWindow(lWidth, abs(lHeight));
}
}
}
}
RECT rc;
pVideoWindow->put_Owner((OAHWND)window);    //We own the window now
pVideoWindow->put_WindowStyle(WS_CHILD);    //you are now a child
GetClientRect(window, &rc);
pVideoWindow->SetWindowPosition(0, 0, rc.right, rc.bottom); //be this big
pVideoWindow->put_Visible(OATRUE);
}*/
}   
}
BOOL CWebcam::StartCamera() {
if(m_bIsStreaming == FALSE)
{
m_bIsStreaming = TRUE;
hr = m_pMediaController->Run();
if(FAILED(hr))
{
//stop parts that ran
m_pMediaController->Stop();
return FALSE;
}
return TRUE;
}
return FALSE;
}
void CWebcam::EndCamera() {
if(m_bIsStreaming)
{
hr = m_pMediaController->Stop();
m_bIsStreaming = FALSE;
//invalidate client rect as well so that it must redraw
}
}
BOOL CWebcam::CaptureToTexture() {
return TRUE;
}
HRESULT CWebcam::InitCaptureGraphBuilder(
IGraphBuilder **ppGraph,  //Receives the pointer.
ICaptureGraphBuilder2 **ppBuild  //Receives the pointer.
)
{
if (!ppGraph || !ppBuild)
{
return E_POINTER;
}
IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuild = NULL;
//Create the Capture Graph Builder.
HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, 
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild );
if (SUCCEEDED(hr))
{
//Create the Filter Graph Manager.
hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void**)&pGraph);
if (SUCCEEDED(hr))
{
//Initialize the Capture Graph Builder.
pBuild->SetFiltergraph(pGraph);
//Return both interface pointers to the caller.
*ppBuild = pBuild;
*ppGraph = pGraph; //The caller must release both interfaces.
return S_OK;
}
else
{
pBuild->Release();
}
}
return hr; //Failed
}
HRESULT CWebcam::EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
{
//Create the System Device Enumerator.
ICreateDevEnum *pSystemDeviceEnumerator;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,  
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pSystemDeviceEnumerator));
if (SUCCEEDED(hr))
{
//Create an enumerator for the category.
hr = pSystemDeviceEnumerator->CreateClassEnumerator(category, ppEnum, 0);
if (hr == S_FALSE)
{
hr = VFW_E_NOT_FOUND;  //The category is empty. Treat as an error.
}
pSystemDeviceEnumerator->Release();
}
return hr;
}
void CWebcam::DisplayDeviceInformation(IEnumMoniker *pEnum)
{
IMoniker *pMoniker = NULL;
int counter = 0;
while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
{
IPropertyBag *pPropBag;
HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
if (FAILED(hr))
{
pMoniker->Release();
continue;  
} 
VARIANT var;
VariantInit(&var);
//Get description or friendly name.
hr = pPropBag->Read(L"Description", &var, 0);
if (FAILED(hr))
{
hr = pPropBag->Read(L"FriendlyName", &var, 0);
}
if (SUCCEEDED(hr))
{
printf("%d: %S\n", counter, var.bstrVal);
VariantClear(&var); 
}
hr = pPropBag->Write(L"FriendlyName", &var);
//WaveInID applies only to audio capture devices.
hr = pPropBag->Read(L"WaveInID", &var, 0);
if (SUCCEEDED(hr))
{
printf("%d: WaveIn ID: %d\n", counter, var.lVal);
VariantClear(&var); 
}
hr = pPropBag->Read(L"DevicePath", &var, 0);
if (SUCCEEDED(hr))
{
//The device path is not intended for display.
printf("%d: Device path: %S\n", counter, var.bstrVal);
VariantClear(&var); 
}
pPropBag->Release();
pMoniker->Release();
counter++;
}
}
HRESULT CWebcam::InitializeVMR(
HWND hwndApp,         //Application window.
IGraphBuilder* pFG,    //Pointer to the Filter Graph Manager.
IVMRWindowlessControl** ppWc,  //Receives the interface.
DWORD dwNumStreams,  //Number of streams to use.
BOOL fBlendAppImage  //Are we alpha-blending a bitmap?
)
{
IBaseFilter* pVmr = NULL;
IVMRWindowlessControl* pWc = NULL;
*ppWc = NULL;
//Create the VMR and add it to the filter graph.
HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL,
CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr);
if (FAILED(hr))
{
return hr;
}
hr = pFG->AddFilter(pVmr, L"Video Mixing Renderer");
if (FAILED(hr))
{
pVmr->Release();
return hr;
}
//Set the rendering mode and number of streams.  
IVMRFilterConfig* pConfig;
hr = pVmr->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig);
if (SUCCEEDED(hr)) 
{
pConfig->SetRenderingMode(VMRMode_Windowless);
//Set the VMR-7 to mixing mode if you want more than one video
//stream, or you want to mix a static bitmap over the video.
//(The VMR-9 defaults to mixing mode with four inputs.)
if (dwNumStreams > 1 || fBlendAppImage) 
{
pConfig->SetNumberOfStreams(dwNumStreams);
}
pConfig->Release();
hr = pVmr->QueryInterface(IID_IVMRWindowlessControl, (void**)&pWc);
if (SUCCEEDED(hr)) 
{
pWc->SetVideoClippingWindow(hwndApp);
*ppWc = pWc;  //The caller must release this interface.
}
}
pVmr->Release();
//Now the VMR can be connected to other filters.
return hr;
}

OriginalL'auteur Darkhydro | 2011-09-26