2010-12-05 6 views
2

Donc, pour obtenir la liste des caméras et permet de selectionner un (C++, Boost, DShow, fenêtres) J'utilise ce code:Windows: comment obtenir des résolutions prises en charge par les caméras?

#include "StdAfx.h" 
#include "list.h" 
#include <windows.h> 
#include <dshow.h> 
#include <boost/lexical_cast.hpp> 

HRESULT CamerasList::EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum) 
{ 
    // Create the System Device Enumerator. 
    ICreateDevEnum *pDevEnum; 
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, 
     CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum)); 

    if (SUCCEEDED(hr)) 
    { 
     // Create an enumerator for the category. 
     hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0); 
     if (hr == S_FALSE) 
     { 
      hr = VFW_E_NOT_FOUND; // The category is empty. Treat as an error. 
     } 
     pDevEnum->Release(); 
    } 
    return hr; 
} 

int CamerasList::SelectFromList() 
{ int i = 0; 
    int SelectedIndex; 
    IEnumMoniker *pEnum; 
    printf("\nLet us select video device\n"); 
    printf("Available Capture Devices are:\n"); 
    HRESULT hr; 
    hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum); 
    if (SUCCEEDED(hr)) 
    { 
     IMoniker *pMoniker = NULL; 

     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)) 
      { 
       std::cout << i; 
       printf(") %S\n", var.bstrVal); 
       i++; 
       VariantClear(&var); 
      } 

      hr = pPropBag->Write(L"FriendlyName", &var); 

      pPropBag->Release(); 
      pMoniker->Release(); 

     } 
     SelectedIndex = 999; 
    if (i <= 0) 
    { 
     cout <<"No devices found. \n " << endl; 
     //cout <<"Please restart application." << endl; 
     //cin.get(); 
     //Sleep(999999); 
    return 999; 

    }else if(i == 1){ 
      cout <<"Default device will be used\n" << std::endl; 
      SelectedIndex = 0; 
     }else{ 
     while(SelectedIndex > i-1 || SelectedIndex < 0) 
     { 
      try{   
      std::string s; 
      std::getline(cin, s, '\n'); 
      SelectedIndex = boost::lexical_cast<int>(s); 
      } 
      catch(std::exception& e){ 
       std::cout <<"please input index from 0 to " << i-1 << std::endl; 
       SelectedIndex = 999; 
      } 
     }} 
     pEnum->Release(); 
    }else 
    { 
     printf("no Video Devices found. \n") ; 
     //cout <<"Please restart application." << endl; 
     //cin.get(); 
     //Sleep(999999); 
     return 999; 
    } 
    return SelectedIndex; 
} 

Je dois obtenir en quelque sorte la liste des caméras pris en charge les résolutions pour la caméra sélectionnée. Comment faire une telle chose?

Répondre

4

En supposant que vous avez ajouté le filtre source de capture au graphique: Une méthode consiste à obtenir l'interface IAMStreamConfig de broche de sortie du filtre de capture puis appeler les IAMStreamConfig :: GetNumberOfCapabilities pour obtenir le nombre de capacités de format pris en charge par le dispositif. Vous pouvez parcourir tous les formats en appelant IAMStreamConfig :: GetStreamCaps avec les index appropriés.

+0

Non, je l'utilise juste pour obtenir la liste des caméras - j'utilise OpenCV pour capturer. Donc, si je ne crée pas un graphique, comment faire une telle chose? Ou comment créer un graphique pour un tel porpus seulement? – Rella

+0

Je ne connais pas d'autre moyen de le faire sans ajouter la source de capture à un graphique afin d'interroger la broche de sortie de l'interface IAMStreamConfig, etc. Qu'en est-il juste de l'ajouter à un graphique, l'interroger, etc. libérant le graphique et les ressources une fois que vous avez l'information désirée? – Ralf

3

Vous pouvez obtenir des résolutions prises en charge sans ajouter la source de capture à un graphique de filtre. Vous devez

  • lient le dispositif moniker à une base filter
  • obtenir une sortie pin de ce filtre
  • enumerate sur media types de cette broche de sortie

Voici comment énumérer les médias types donnés media type enumerator

AM_MEDIA_TYPE* mediaType = NULL; 
VIDEOINFOHEADER* videoInfoHeader = NULL; 
while (S_OK == mediaTypesEnumerator->Next(1, &mediaType, NULL)) 
{ 
    if ((mediaType->formattype == FORMAT_VideoInfo) && 
     (mediaType->cbFormat >= sizeof(VIDEOINFOHEADER)) && 
     (mediaType->pbFormat != NULL)) 
    { 
     videoInfoHeader = (VIDEOINFOHEADER*)mediaType->pbFormat; 
     videoInfoHeader->bmiHeader.biWidth; // Supported width 
     videoInfoHeader->bmiHeader.biHeight; // Supported height 
    } 
    FreeMediaType(*mediaType); 
} 
+0

Merci, juste ce dont j'avais besoin. Cependant, apparemment, nous sommes supposés utiliser 'DeleteMediaType' dans ce contexte ([link] (https://msdn.microsoft.com/fr-fr/library/windows/desktop/dd376602 (v = vs.85) .aspx)). De même (de toute façon) ne peut pas utiliser 'pbFormat' par la suite. – entheh

Questions connexes