【问题标题】:Enumerating UVC Properties items of a property set of a camera枚举相机属性集的 UVC 属性项
【发布时间】: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;

【问题讨论】:

    标签: video-streaming directshow ms-media-foundation wdm


    【解决方案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 接口。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-04
    • 2020-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多