0

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

现在 IAMVideoProcAmp 支持 10 个属性 ,IAMCameraControl 支持 7 个属性

并非所有相机都支持所有属性项。我想知道任何相机支持的确切属性(枚举索引/值)。我们可以使用 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;
4

1 回答 1

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;
    }
    ...
}
于 2013-03-15T09:00:08.580 回答