Windows: how to get cameras supported resolutions?
Asked Answered
Z

2

1

So to get cameras list and let user select one (C++, Boost, dshow, windows) I use such code:

#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;
}

I need to somehow get list of camera supported resolutions for selected camera. How to do such thing?

Zollie answered 5/12, 2010 at 16:21 Comment(0)
A
5

Assuming that you've added the capture source filter to the graph: One method is to get the IAMStreamConfig interface of the capture filter's output pin and then call the IAMStreamConfig::GetNumberOfCapabilities to get the number of format capabilities supported by the device. You can iterate over all formats by calling the IAMStreamConfig::GetStreamCaps with the appropriate indices.

Apennines answered 5/12, 2010 at 17:3 Comment(2)
No, I actually just use it to get cameras list - I use OpenCV to capture. So If I do not create a graph how to do such thing? Or how to create graph for such porpus only?Zollie
I don't know of any other way to do it without adding the capture source to a graph in order to query the output pin for the IAMStreamConfig interface, etc. What about just adding it to a graph, querying it, etc and then releasing the graph and the resources once you've got the desired info?Apennines
S
4

You can get supported resolutions without adding the capture source to a filter graph. You need to:

Here is how to enumerate the media types given a 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);
}
Spada answered 28/3, 2013 at 18:1 Comment(2)
Thanks, just what I needed. However, apparently we're supposed to use DeleteMediaType in this context (link). Also (either way) can't use pbFormat afterwards.Trainor
Hello, very usefull example, but could you please help to find a code example of how to 1.bind the device moniker to a base filter 2.get an output pin from that filter 3.enumerate over media types of that output pin i need a directshow camera resolution enumerate function. Thank youAutomat

© 2022 - 2024 — McMap. All rights reserved.