2010-01-17 1 views
0

J'ai créé l'exemple AMCap sous le mode direct dans SDK. Il est capable de gérer 2 ou plusieurs web cam, comment puis-je modifier le programme pour que je les utilise simultanément ... comme appuyer sur un bouton qui dit «commencer la capture» et s'assurer que toutes les caméras commencent à capturer et un bouton qui dit «stop capture 'pour arrêter toutes les caméras. Je veux que les images de différentes caméras soient sauvegardées dans des fichiers différents. Je suis nouveau en C++ et toute forme d'aide est appréciée! Merci pour votre temps!Plusieurs webcams dans AMCap

Répondre

0

Utilisez l'outil GraphEdit. Là, vous pouvez construire votre propre graphique avec tous les périphériques d'entrée vidéo connectés. S'il vous plaît voir http://en.wikipedia.org/wiki/GraphEdit

+0

GraphEdit est un bon outil de prototypage pour la création graphiques, mais je pense que le PO veut réaliser cela dans le code. GraphStudio est une meilleure alternative à GraphEdit;) http://blog.monogram.sk/janos/tools/monogram-graphstudio/ –

0

Si vous venez de commencer avec la programmation DirectShow, cela peut être un peu une ascension, mais j'espère que cela vous aidera ou vous orientera dans la bonne direction.

M $ DN a une page décrivant how to select a capture device. C'est un peu mince sur les exemples, donc j'ai fourni une implémentation simple ci-dessous.

La théorie est que vous devez énumérer tous les périphériques du CLSID_VideoInputDeviceCategory et essayer de créer un graphique de rendu pour chaque élément valide de la catégorie.

Je vais d'abord vous montrer le code pour itérer les noms des périphériques de la catégorie. Vous trouverez ci-dessous 3 fonctions statiques que vous pouvez utiliser pour itérer les périphériques dans une catégorie. Une fois que vous avez ajouté ces fonctions à votre projet, vous pouvez lister les périphériques dans la catégorie de périphériques d'entrée vidéo en appelant la fonction suivante:

ListDevicesInCategory(CLSID_VideoInputDeviceCategory); 

D'accord, voici les trois fonctions. ListDevicesInCategory() est l'endroit où le travail se passe. Cela dépend de deux autres fonctions, FindDeviceInCategory() et CountDevicesInCategory()

#define RFAIL(x) { HRESULT hr = x; if(FAILED(hr)) {return hr;} } 


static HRESULT FindDeviceInCategory(IBaseFilter** pSrc, const IID& cls, wstring& wFilterName,int devNum) 
{ 
    CComPtr<ICreateDevEnum> spDevEnum; 
    CComPtr<IEnumMoniker> spEnum; 
    int      i; 

    RFAIL(spDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum)); 
    RFAIL(spDevEnum->CreateClassEnumerator(cls, &spEnum, 0)); 

    if(spEnum == 0) 
     return E_FAIL; 

    for(i = 0; i >= 0; i++) 
    { 
     CComPtr<IMoniker> spiMoniker; 

     if(spEnum->Next(1, &spiMoniker, 0) != S_OK)   
      return E_FAIL;   

     if(devNum == i) 
     { 
      CComVariant varName; 
      CComPtr<IPropertyBag> spiPropBag; 
      RFAIL(spiMoniker->BindToStorage(0, 0, IID_IPropertyBag,reinterpret_cast<void**>(&spiPropBag))); 
      RFAIL(spiPropBag->Read(L"FriendlyName", &varName, 0)); 
      RFAIL(spiMoniker->BindToObject(0, 0, IID_IBaseFilter, reinterpret_cast<void**>(pSrc))); 
      wFilterName = V_BSTR(&varName); 

      varName.Clear(); 
      return S_OK; 
     } 
    } 

    return E_FAIL; 
} 

static HRESULT CountDevicesInCategory(int *pCount, const IID& categoryClass) 
{ 
    // pass in a category class like CLSID_VideoInputDeviceCategory, writes the count of the number of filters in that category 
    // available on the local machine 
    HRESULT hr = S_OK; 

    CComPtr<ICreateDevEnum> spIDevEnum; 
    CComPtr<IEnumMoniker> spIEnum; 
    CComPtr<IMoniker>  spIMoniker; 

    hr = CoCreateInstance(CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast<void**>(&spIDevEnum)); 
    if(! SUCCEEDED(hr) || hr == S_FALSE) 
    { 
     *pCount = 0; 
     return hr; 
    } 

    hr = spIDevEnum->CreateClassEnumerator(categoryClass, &spIEnum, 0); 
    if(! SUCCEEDED(hr) || hr == S_FALSE) 
    { 
     *pCount = 0; 
     return hr; 
    } 

    if(spIEnum) 
    { 
     while(spIEnum->Next(1, &spIMoniker, 0) == S_OK) 
     { 
      (*pCount) ++; 
      spIMoniker.Detach(); 
     }  
    } 

    return S_OK; 
} 

static HRESULT ListDevicesInCategory(const GUID & cls) 
{ 
    CComPtr<IBaseFilter> spSource; 
    wstring *    psNextFilter  = NULL; 
    int      nDeviceNum   = 0; 
    int      nTotalNumDevices = 0; 
    HRESULT     hr     = S_OK; 
    bool     bComplete   = false;  
    DeviceNames    CaptureDeviceNames; 


    if(FAILED(CountDevicesInCategory(&nTotalNumDevices, (IID)cls))) 
     bComplete = TRUE; 

    if(nTotalNumDevices == 0) 
     bComplete = TRUE; 


    while(! bComplete) 
    { 
     psNextFilter = new std::wstring; 

     hr = FindDeviceInCategory(&spSource, (IID)cls, *psNextFilter, nDeviceNum++); 

     if(SUCCEEDED(hr) && spSource ) 
     { 
      if (*psNextFilter) 
      { 
       wcout << *psNextFilter << endl; 
       delete *psNextFilter; 
       psNextFilter = NULL; 
      } 

      spSource.Release(); 
      spSource = NULL; 
     } 
     else 
      bComplete = TRUE; 
    }   

    return S_OK; 
} 

Une fois que vous avez identifié un élément dans une catégorie qui vous intéresse, vous pouvez l'ajouter à un graphique à l'appel IGraphBuilder::AddFilter.

Pour ajouter un filtre à votre graphique, vous devez d'abord ajouter un IBaseFilter * à ce filtre. J'ai encore une fonction pour vous faire ça.

Définir un pointeur intelligent IBaseFilter:

CComPtr<IBaseFilter> spSource; 

ANNEXER au filtre:

m_spSource.Attach(
       GetFilter(CLSID_VideoInputDeviceCategory, CComBSTR(L"Osprey-450e Video Device 1A")) 
     ); 

est ici cette dernière fonction - GetFilter:

static IBaseFilter * GetFilter(REFCLSID clsidDeviceClass, CComBSTR & sName) 
{ 
    HRESULT    hr; 
    IBaseFilter *  pRetFilter  = NULL; 
    ICreateDevEnum * pSysDevEnum  = NULL; 
    IEnumMoniker *  pEnum   = NULL; 
    IMoniker *   pMoniker  = NULL; 
    int     nSameSrcCounter = 0; 

    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pSysDevEnum); 

    if(pSysDevEnum) 
     hr = pSysDevEnum->CreateClassEnumerator(clsidDeviceClass, &pEnum, 0); 

    if (hr != S_OK) 
     return NULL;  

    USES_CONVERSION; 


    while (pEnum->Next(1, &pMoniker, NULL) == S_OK) 
    { 
     IPropertyBag *pPropBag = NULL; 
     VARIANT var; 
     VariantInit(&var); 

     pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); 

     hr = pPropBag->Read(L"FriendlyName", &var, 0); 
     if (SUCCEEDED(hr)) 
     { 
      if(sName == OLE2T(var.bstrVal)) 
      {   
       hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pRetFilter); 
       if (FAILED(hr))     
        pRetFilter = NULL;     

       VariantClear(&var); 
       pPropBag->Release(); 
       pMoniker->Release(); 
       break; 
      } 
     } 

     VariantClear(&var); 
     pPropBag->Release(); 
     pMoniker->Release(); 
    } 

    pSysDevEnum->Release(); 
    pEnum->Release(); 

    return pRetFilter; 
}