枚举相机属性集的 UVC 属性项

Posted

技术标签:

【中文标题】枚举相机属性集的 UVC 属性项【英文标题】:Enumerating UVC Properties items of a property set of a camera 【发布时间】:2013-02-14 12:22:49 【问题描述】:

我正在使用 IKsTopologyInfo 和 IKsControl 接口枚举相机的 UVC 属性。我同时使用 MFT 和直接显示此代码。在枚举期间,我得到各种 GUID,例如 CLSID_IAMCameraControl、CLSID_IAMVideoProcAmp 等等。

现在 IAMVideoProcAmp 支持 10 properties 和 IAMCameraControl 支持 7 properties

并非所有相机都支持所有属性项。我想知道任何相机支持的确切属性(枚举索引/值)。我们可以使用 IKsTopologyInfo 和 IKsControl 查询吗?还有其他方法吗?

这是枚举属性的代码,即此代码为我提供接口 CLSID_IAMCameraControl,CLSID_IAMVideoProcAmp

HRESULT                     hRet        = S_OK; 
CComPtr<IKsTopologyInfo>    ksTopology  = NULL;
BYTE*                       pList       = NULL;

do
           

    if(!m_pMediaSource)
        break;  

    if(m_SuppPropSetGUIDS.size())
        break;

    hRet = m_pMediaSource->QueryInterface(IID_PPV_ARGS(&ksTopology));
    if(FAILED(hRet))
        break;

    ksTopology->get_NumNodes(&m_dwNumNodes);
    for (ULONG ulNode=0; ulNode < m_dwNumNodes; ulNode++ )
    
        CComPtr<IKsControl> ksControl       = 0;
        GUID                nodeType        = GUID_NULL;
        DWORD               dwBytesReturned = 0;

        KSPROPERTY      KsProp = 0;
        KsProp.Set      = GUID_NULL;
        KsProp.Id       = 0; // Ignored
        KsProp.Flags    = KSPROPERTY_TYPE_SETSUPPORT;

        KSP_NODE            KsNode          = 0;
        KsNode.Property.Set = GUID_NULL;
        KsNode.NodeId = ulNode;
        KsNode.Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;

        ksTopology->get_NodeType(ulNode, &nodeType);

        hRet = ksTopology->CreateNodeInstance(ulNode, IID_PPV_ARGS(&ksControl));
        if(FAILED(hRet))
            continue;               

        hRet = ksControl->KsProperty(&KsProp, sizeof(KSPROPERTY), NULL, NULL, &dwBytesReturned);    
        if( hRet == HRESULT_FROM_WIN32(ERROR_MORE_DATA) && dwBytesReturned )
                   
            pList = (BYTE*)calloc(dwBytesReturned, sizeof(BYTE) );
            if ( pList == NULL )
                continue;
            hRet = ksControl->KsProperty(&KsProp, sizeof(KSPROPERTY), pList, dwBytesReturned, &dwBytesReturned);    


            if(FAILED(hRet))
                break;              
        
        else
            continue;

        GUID* pGuidList = (GUID*)pList;
        int iCount = dwBytesReturned/sizeof(GUID);
        for(int i = 0; i < iCount; i++ )
        
            if( !LookUpPS( &pGuidList[i] ) )
                m_SuppPropSetGUIDS.push_back( pGuidList[i] );
        
        if(pList)
            free(pList);
        pList = NULL;

    
while(FALSE);

if(pList)
    free(pList);
pList = NULL;

return hRet;

【问题讨论】:

【参考方案1】:

为此使用 IAMVideoProcAmpIAMCameraControl 的 DirectShow 接口。

这是一个 C# 类,它封装了 CameraControl 并删除了大部分令人痛苦的部分。 VideoProcAmp 完全类似:

public class CameraControlSetting : IDisposable

    private readonly CameraControlProperty property;
    private IAMCameraControl controlInterface;
    private int min;
    private int max;
    private int steppingDelta;
    private int defaultValue;
    public CameraControlFlags CapabilityFlags;

    public int Min
    
        get  return min; 
    

    public int Max
    
        get  return max; 
    

    public int SteppingDelta
    
        get  return steppingDelta; 
        set  steppingDelta = value;   // Shouldn't be exposed, but WhiteBalanceSteppingDelta is often 1!
    

    public int DefaultValue
    
        get  return defaultValue; 
    


    public CameraControlSetting(CameraControlProperty property, IAMCameraControl controlInterface)
    
        this.property = property;
        this.controlInterface = controlInterface;
    

    public void GetRange()
    
        if (controlInterface == null) return;
        controlInterface.GetRange(property, out min, out max, out steppingDelta, out defaultValue,
                                  out CapabilityFlags);
        GetCurrentValueAndFlags();
    

    private void GetCurrentValueAndFlags()
    
        if (controlInterface == null) return;
        controlInterface.Get(property, out currentValue, out currentFlags);
    

    private void SetCurrentValueAndFlags()
    
        if (controlInterface == null) return;
        controlInterface.Set(property, currentValue, currentFlags);
    

    private CameraControlFlags currentFlags;
    public CameraControlFlags CurrentFlags
    
        get  return currentFlags; 
        set
        
            GetCurrentValueAndFlags();  
            currentFlags = value;
            SetCurrentValueAndFlags();
        
    

    private int currentValue;
    public int CurrentValue
    
        get  return currentValue; 
        set
        
            currentFlags = CameraControlFlags.Manual;
            currentValue = value;
            SetCurrentValueAndFlags();
        
    

    public void Dispose()
    
        controlInterface = null;
    

那么,你可以像下面这样使用上面的类:

public IAMCameraControl CameraControl  get  return m_pCaptureFilter as IAMCameraControl;  

public CameraControlSetting Zoom  get; private set; 
public CameraControlSetting Focus  get; private set; 

public bool HasAutoFocus  get  return (Focus != null) && ((Focus.CapabilityFlags & CameraControlFlags.Auto) == CameraControlFlags.Auto);  

private void GetCameraFeatures()

    Zoom = new CameraControlSetting(CameraControlProperty.Zoom, CameraControl);
    Focus = new CameraControlSetting(CameraControlProperty.Focus, CameraControl);

    // Get the CameraControl Properties
    Zoom.GetRange();
    Focus.GetRange();
    if (HasAutoFocus)
    
        Focus.CurrentFlags = CameraControlFlags.Auto;
    
    ...

【讨论】:

谢谢..我已经用 C++ 实现了它。我只是想知道为什么 IKsTopologyInfo 在这里不起作用。 一种可能性:一些摄像机不使用 KsProxy.ax,而是提供了自己的 DirectShow 视频捕获过滤器。因此他们可能没有实现 IKsPropertySet 接口。

以上是关于枚举相机属性集的 UVC 属性项的主要内容,如果未能解决你的问题,请参考以下文章

UVCAndroid,安卓UVC相机通用开发库(支持多预览和多摄像头)

uvc是啥

如何更改 Android 相机属性?

three.js 相机camera位置属性设置详解

海康360°如何调自动训拍

无法读取未定义的属性“getPicture” - 离子相机