Achtergrondsegmentatie, ondiepe focusmodus en oogstaarmodus voor stuurprogramma's voorbeeld

Dit is een voorbeeld van de implementatie van achtergrondsegmentatie in ondiepe focusmodus en oogstaarmodus, twee nieuwe bitvelden die worden geïntroduceerd in Windows 11, versie 22H2.

Deze besturingselementen worden doorgaans geïmplementeerd in C++, als onderdeel van de uitbreiding van de gebruikersmodus van een Avstream-camerastuurprogramma in Apparaat MFT.

Opmerking

Het WinRT_ExtendedControlAndMetadataSample C# UWP-toepassingsvoorbeeld op GitHub toont een cameravoorbeeld en interageert met de uitgebreide besturingselementen.

SampleMFT.h

Class CSampleMFT //Snipped from SampleDeviceMFT Implementation
{
...
Private:
...
    VOID SetBackgroundSegmentationShallowFocus(BOOLEAN enabled)
    {
        m_backgroundSegmentationShallowFocusEnabled = enabled;
    }
    BOOLEAN GetBackgroundSegmentationShallowFocus()
    {
        return m_backgroundSegmentationShallowFocusEnabled;
    }
    constexpr ULONGLONG SupportedBackgroundSegmentation()
    {
        return  KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_BLUR |
                KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_MASK |
                KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_SHALLOWFOCUS;
    }

    VOID SetEyeGazeCorrectionMode(DWORD flags)
    {
        m_eyeGazeCorrectionMode = flags;
    }
    DWORD GetEyeGazeCorrectionMode()
    {
        return m_eyeGazeCorrectionMode;
    }
    BOOLEAN m_backgroundSegmentationShallowFocusEnabled;
    DWORD m_eyeGazeCorrectionMode;
};

SampleMFT.cpp

// KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_SHALLOWFOCUS
HRESULT CSampleMft::BackgroundSegmentationHandler(
    _In_ PKSPROPERTY property,
    _In_ LPVOID data,
    _In_ ULONG outputBufferLength,
    _Inout_ PULONG bytesReturned)
{
    *bytesReturned = 0;
    if (property->Flags & KSPROPERTY_TYPE_SET)
    {
        if (outputBufferLength == 0)
        {
            *bytesReturned = sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(KSCAMERA_EXTENDEDPROP_VALUE);
            RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_MORE_DATA));
        }
        else if (outputBufferLength < sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(KSCAMERA_EXTENDEDPROP_VALUE))
        {
            RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_MORE_DATA));
        }
        else if (data && outputBufferLength >= sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(KSCAMERA_EXTENDEDPROP_VALUE))
        {
            PBYTE payload = (PBYTE)data;
            PKSCAMERA_EXTENDEDPROP_HEADER extendedHeader = (PKSCAMERA_EXTENDEDPROP_HEADER)payload;
            // The extended value is unused for SET with this control, only flags are expected
            PKSCAMERA_EXTENDEDPROP_VALUE extendedValue = (PKSCAMERA_EXTENDEDPROP_VALUE)(payload + sizeof(KSCAMERA_EXTENDEDPROP_HEADER));
            if (extendedHeader->Flags & ~SupportedBackgroundSegmentation())
            {
                RETURN_HR(E_INVALIDARG);
            }

            bool shallowFocus = WI_IsFlagSet((extendedHeader->Flags, KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_SHALLOWFOCUS);
            bool blur = WI_IsFlagSet((extendedHeader->Flags, KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_BLUR);
            bool mask = WI_IsFlagSet((extendedHeader->Flags, KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_MASK);

            // If you ask for shallow focus, you must also ask for blur.
            if (shallowFocus && !blur)
            {
                RETURN_HR(E_INVALIDARG);
            }
            SetBackgroundSegmentationShallowFocus(shallowFocus);
            SetBackgroundSegmentationBlur(blur);
            SetBackgroundSegmentationMask(mask);
        }
        else
        {
            RETURN_IF_FAILED(E_INVALIDARG);
        }
    }
    else if (property->Flags & KSPROPERTY_TYPE_GET)
    {
        if (outputBufferLength == 0)
        {
            *bytesReturned = sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(m_configCaps);
            RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_MORE_DATA));
        }
        else if (outputBufferLength < sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(m_configCaps))
        {
            RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_MORE_DATA));
        }
        else if (data && outputBufferLength >= sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(m_configCaps))
        {
            PBYTE payload = (PBYTE)data;
            PKSCAMERA_EXTENDEDPROP_HEADER extendedHeader = (PKSCAMERA_EXTENDEDPROP_HEADER)(payload);
            extendedHeader->Capability = KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_MASK |
                                         KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_BLUR |
                                         KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_SHALLOWFOCUS |
                                         KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_OFF;

            if (GetBackgroundSegmentationMask())
            {
                extendedHeader->Flags |= KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_MASK;
            }

            if (GetBackgroundSegmentationBlur())
            {
                extendedHeader->Flags |= KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_BLUR;
            }
            else if (GetBackgroundSegmentationShallowFocus())
            {
                extendedHeader->Flags |= KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_BLUR | KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_SHALLOWFOCUS;
            }
            else
            {
                extendedHeader->Flags = KSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_OFF;
            }
            extendedHeader->Result = 0;
            extendedHeader->Size = sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(m_configCaps);
            extendedHeader->Version = 1;
            
            PKSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_CONFIGCAPS configCap = (PKSCAMERA_EXTENDEDPROP_BACKGROUNDSEGMENTATION_CONFIGCAPS)( payload + sizeof(KSCAMERA_EXTENDEDPROP_HEADER)));
            memcpy(configCap, m_configCaps, sizeof(m_configCaps));
            *bytesReturned = sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(m_configCaps);
        }
    }

    return S_OK;
}

// KSCAMERA_EXTENDEDPROP_EYEGAZECORRECTION_STARE 
HRESULT CSampleMft::EyeGazeCorrectionHandler(   
    _In_       PKSPROPERTY property,   
    _In_       LPVOID      data,   
    _In_       ULONG       outputBufferLength,   
    _Inout_    PULONG      bytesReturned   
)   
{   
    HRESULT hr = S_OK;   
    *bytesReturned = 0;   

    if (property->Flags & KSPROPERTY_TYPE_SET)   
    {   
        if (outputBufferLength == 0) 
        {   
            *bytesReturned = sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(KSCAMERA_EXTENDEDPROP_VALUE);   
            RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_MORE_DATA));   
        }   
        else if (outputBufferLength < sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(KSCAMERA_EXTENDEDPROP_VALUE))   
        {   
            RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_MORE_DATA));   
        }   
        else if (data && outputBufferLength >= sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(KSCAMERA_EXTENDEDPROP_VALUE))   
        {   
            PBYTE payload = (PBYTE)data;   
            PKSCAMERA_EXTENDEDPROP_HEADER extendedHeader = (PKSCAMERA_EXTENDEDPROP_HEADER)payload;   
            //   
            // Use the extended value to make changes to the property.. refer documentation   
            // PKSCAMERA_EXTENDEDPROP_VALUE extendedValue = (PKSCAMERA_EXTENDEDPROP_VALUE)(payload + sizeof(KSCAMERA_EXTENDEDPROP_HEADER));   
            //
            if ( (extendedHeader->Flags == KSCAMERA_EXTENDEDPROP_EYEGAZECORRECTION_ON) ||
                 (extendedHeader->Flags == (KSCAMERA_EXTENDEDPROP_EYEGAZECORRECTION_ON | KSCAMERA_EXTENDEDPROP_EYEGAZECORRECTION_STAREMODE)) ||
                 (extendedHeader->Flags == KSCAMERA_EXTENDEDPROP_EYEGAZECORRECTION_OFF) )
            {
                SetEyeGazeCorrectionMode (extendedHeader->Flags);   
            }
            else
            {
                RETURN_HR(E_INVALIDARG);
            } 
            *bytesReturned = sizeof(PKSCAMERA_EXTENDEDPROP_HEADER) + sizeof(KSCAMERA_EXTENDEDPROP_VALUE);   
        }   
        else  
        {  
            RETURN_IF_FAILED(E_INVALIDARG);  
        }  
    }   
    else if (property->Flags & KSPROPERTY_TYPE_GET)   
    {   
        if (outputBufferLength == 0)   
        {   
            *bytesReturned = sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(KSCAMERA_EXTENDEDPROP_VALUE);   
            RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_MORE_DATA));  
        }   
        else if (outputBufferLength < sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(KSCAMERA_EXTENDEDPROP_VALUE)) 
        {   
            RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_MORE_DATA));  
        }   
        else if (data && outputBufferLength >= sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(KSCAMERA_EXTENDEDPROP_VALUE))   
        {         
            PBYTE payload = (PBYTE)data;   
            PKSCAMERA_EXTENDEDPROP_HEADER extendedHeader = (PKSCAMERA_EXTENDEDPROP_HEADER)(payload);   
            //   
            // Use the extended value to make changes to the property.. refer documentation   
            // PKSCAMERA_EXTENDEDPROP_VALUE extendedValue = (PKSCAMERA_EXTENDEDPROP_VALUE)(payload +sizeof(KSCAMERA_EXTENDEDPROP_HEADER));   
            //   
            extendedHeader->Capability = KSCAMERA_EXTENDEDPROP_EYEGAZECORRECTION_OFF |  
                                         KSCAMERA_EXTENDEDPROP_EYEGAZECORRECTION_ON |   
                                         KSCAMERA_EXTENDEDPROP_EYEGAZECORRECTION_STAREMODE;   

            extendedHeader->Flags = GetEyeGazeCorrectionMode();
            extendedHeader->Result = 0;   
            extendedHeader->Size = sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(KSCAMERA_EXTENDEDPROP_VALUE);   
            extendedHeader->Version = 1;   

            *bytesReturned = sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof(KSCAMERA_EXTENDEDPROP_VALUE);   
        }   
    }   
    return S_OK;   
}

Zie ook

KSPROPERTY_CAMERACONTROL_EXTENDED_BACKGROUNDSEGMENTATION

KSPROPERTY_CAMERACONTROL_EXTENDED_EYEGAZECORRECTION