Sdílet prostřednictvím


Vzorový kód (profil fotoaparátu V2)

Následující části obsahují vzorový kód, který ukazuje, jak je možné využívat nové povrchy rozhraní API. Každá část popisuje scénář ukázkového kódu.

Ukázka 1

Zařízení MFT poskytnuté systémem IHV/OEM bude muset poskytnout sadu profilů fotoaparátů podporovaných podkladovým snímačem a poskytovateli internetových služeb. Tato metoda se publikuje během metody MMFDeviceTransform::InitializeTransform() zařízení MFT.

Poskytnuté profily fotoaparátu musí být nastaveny v úložišti MMFAttributes připojené transformace (to je úložiště dotazů kanálu po úplném vytvoření kanálu).

Tato ukázka je typická v případě, že IHV dodává jeden referenční balíček ovladačů, který povolil profily, ale OEM se může rozhodnout spárovat modul fotoaparátu s různými moduly snímačů. V takových případech, protože senzory nemusí mít stejné možnosti, je nutné aktualizovat profily za běhu. To provádí DMFT.

IFACEMETHODIMP
SampleDMFT::InitializeTransform(
    _In_ IMFAttributes *pAttributes 
    )
{
    ComPtr<IMFTransform>                spTransform;
    ComPtr<IMFAttributes>               spAttributes;
    ComPtr<IMFSensorProfileCollection>  spProfileCollection;
    ComPtr<IMFSensorProfile>            spProfile;


    if (nullptr == pAttributes)
    {
        return E_INVALIDARG;
    }

    // Get the connected KSCONTROL interface, this is the 
    // IMFTransform of the up stream transform--which will
    // be the devproxy if only one DMFT is present, or
    // will be forwarded by the platform DMFT if that is
    // in between the IHV/OEM DMFT and devproxy.
    // In either case, the IHV/OEM DMFT won't need to know
    // the topology.
    RETURN_IF_FAILED (pAttributes->GetUnknown(MF_DEVICEMFT_CONNECTED_FILTER_KSCONTROL, 
                                              IID_PPV_ARGS(&spTransform)));
    RETURN_IF_FAILED (spTransform->GetAttributes(&spAttributes));

    // Create an empty profile collection...
    RETURN_IF_FAILED (MFCreateSensorProfileCollection(&spProfileCollection));

    // In this example:
    // Pin0 - Preview pin.
    // Pin1 - Capture/Record pin.
    // Pin2 - Photo pin.
    // Pin3 - IR pin.
    // 
    // Legacy profile is mandatory.  This is to ensure non-profile
    // aware applications can still function, but with degraded
    // feature sets.
    RETURN_IF_FAILED (MFCreateSensorProfile(KSCAMERAPROFILE_Legacy, 0, nullptr, 
                                            spProfile.ReleaseAndGetAddressOf()));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(0, L"((RES==;FRT<=30,1;SUT==))"));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(1, L"((RES==;FRT<=30,1;SUT==))"));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(2, L"((RES==;FRT<=30,1;SUT==))"));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(3, L"((RES==;FRT<=30,1;SUT==))"));
    RETURN_IF_FAILED (spProfileCollection->AddProfile(spProfile));

    // High Frame Rate profile will only allow preview & record/capture pin.
    RETURN_IF_FAILED (MFCreateSensorProfile(KSCAMERAPROFILE_HighFrameRate, 0, nullptr, 
                                            spProfile.ReleaseAndGetAddressOf()));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(0, L"((RES==;FRT==;SUT==))"));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(1, L"((RES==;FRT>=60,1;SUT==))"));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(2, L"(!)"));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(3, L"(!)"));
    RETURN_IF_FAILED (spProfileCollection->AddProfile(spProfile));

    // HighQualityPhoto profile will only allow preview and photo pin.
    RETURN_IF_FAILED (MFCreateSensorProfile(KSCAMERAPROFILE_HighQualityPhoto, 0, nullptr, 
                                            spProfile.ReleaseAndGetAddressOf()));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(0, L"((RES==;FRT==;SUT==))"));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(1, L"(!)"));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(2, L"((RES==;FRT==;SUT==))"));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(3, L"(!)"));
    RETURN_IF_FAILED (spProfileCollection->AddProfile(spProfile));

    // Face auth only allows 720p@30fps from preview and any from IR pin.
    RETURN_IF_FAILED (MFCreateSensorProfile(KSCAMERAPROFILE_FaceAuth_Mode, 0, nullptr, 
                                            spProfile.ReleaseAndGetAddressOf()));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(0, L"((RES==1280,720;FRT==30,1;SUT==))"));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(1, L"(!)"));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(2, L"(!)"));
    RETURN_IF_FAILED (spProfile->AddProfileFilter(3, L"((RES==;FRT==;SUT==))"));
    RETURN_IF_FAILED (spProfileCollection->AddProfile(spProfile));


    // Se the profile collection to the attribute store of the IMFTransform.
    RETURN_IF_FAILED (spAttributes->SetUnknown(MF_DEVICEMFT_SENSORPROFILE_COLLECTION, 
                                               spProfileCollection));

    // ... Rest of the InitializeTransform logic...
}

Ukázka 2

V tomto scénáři předpokládáme, že technologie IHV/OEM poskytla transformaci skupiny senzorů (SGT), která syntetizuje tok médií z několika fyzických zařízení. Předpokládáme také, že technologie IHV poskytla jedinou referenční implementaci pro ovladače kamery pro každé fyzické zařízení (pravděpodobně zdrojové od různých dodavatelů), ale výrobce OEM (nebo jiný IHV) se rozhodl spárovat ovladač fotoaparátu s různými senzory nebo poskytovatelem internetových služeb.

Výsledkem je, že některé možnosti deklarované referenční implementací už nejsou platné. SGT aktualizuje nebo odebere profily, které poskytují přesnější popis možností základního hardwaru.

Následující ukázka je implementace MMFSensorTransformFactory::InitializeFactory metoda. To implementuje IHV/OEM, který vytvoří balíček ovladačů pro subsystém kamery.

IFACEMETHODIMP
SampleSensorTransformFactory::InitializeFactory(
    _In_ DWORD dwMaxTransformCount, 
    _In_ IMFCollection* sensorDevices, 
    _In_opt_ IMFAttributes* pAttributes 
    )
{
    DWORD sensorDeviceCount = 0;
    ComPtr<IUnknown> unknown;

    if (nullptr == sensorDevices)
    {
        return E_INVALIDARG;
    }

    // For this example, the IHV/OEM added a SGT to a multi-camera
    // setup.  And the SGT is responsible for updating the profile
    // information available from each of the physical cameras, and
    // leave it's own profile as "blank".  This has the net effect
    // of having the SGT support any profile the physical devices
    // expose.
    RETURN_IF_FAILED (sensorDevices->GetElementCount(&sensorDeviceCount));
    for (DWORD idx = 0; idx < sensorDeviceCount; idx++)
    {
        ComPtr<IMFGetService> service;
        ComPtr<IMFSensorProfileCollection> profileCollection;
        SENSORPROFILEID sensorProfileId;

        RETURN_IF_FAILED (sensorDevices->GetElement(idx, 
                              unknown.ReleaseAndGetAddressOf()));
        RETURN_IF_FAILED (unknown.As(service.ReleaseAndGetAddressOf()));
        RETURN_IF_FAILED (service->GetService(GUID_NULL, 
                              ID_PPV_ARGS(profileCollection.ReleaseAndGetAddressOf())));

        // Let's assume that for this ISP/sensor, we cannot support
        // photo sequence but our reference driver published a single
        // photo sequence profile whose ID is hardcoded to a static
        // variable s_PhotoSequenceProfileId.
        RETURN_IF_FAILED (profileCollection->RemoveProfile(&s_PhotoSequenceProfileId));

        // Let's also assume this is a low cost ISP/sensor so our driver
        // cannot support Video HDR (VHDR) control for high frame rate
        // recording and our reference implementation published multiple
        // high frame rate recording profile.
        // 
        // Also for this combination of ISP/sensor, we cannot support
        // Face Auth (IR doesn't support alternate illumination option).
        // So we need to remove all Face Auth from our collection.
        for (DWORD profileIdx = 0; 
                   profileIdx < profileCollection->GetProfileCount();)
        {
            ComPtr<IMFSensorProfile> profile;

            RETURN_IF_FAILED (profileCollection->GetProfile(profileIdx, 
                                  profile.ReleaseAndGetAddressOf()));

            RETURN_IF_FAILED (profile->GetProfileId(&profileId));
            if (profileId.Type == KSCAMERAPROFILE_HighFrameRate)
            {
                RETURN_IF_FAILED (profile->AddBlockedControl(L"VHDR"));
            }
            if (profileId.Type == KSCAMERAPROFILE_FaceAuth_Mode)
            {
                RETURN_IF_FAILED (profileCollection->RemoveProfileByIndex(profileIdx));
            }
            else
            {
                profileIdx++;
            }
        }
    }

    // ... Rest of the InitializeFactory logic...
}

Ukázka 3

Na základě vybraného profilu pro konkrétní zařízení určete, který typ média z tohoto zařízení se podporuje nebo nepodporuje pro tento profil, pomocí informací O MMFSensorStream.

Tato ukázka ukazuje, jak lze profil využívat v klientském prostoru při přímém použití rozhraní API Win32. Rozhraní API WinRT už tuto logiku implementuje při použití prostřednictvím rozhraní API cameraProfile.

HRESULT
CheckMediaTypesOnPin(
    _In_z_ LPCWSTR deviceSymbolicName,
    _In_ UINT32 pinId,
    _In_ SENSORPROFILEID* profileId,
    _COM_Outptr_ IMFCollection** mediaTypeCollection
    )
{
    HRESULT hr = S_OK;
    ComPtr<IMFCollection> collection;
    ComPtr<IMFSensorGroup> sensorGroup;
    ComPtr<IMFGetService> service;
    ComPtr<IMFSensorProfileCollection> profileCollection;
    ComPtr<IMFSensorProfile> profile;
    ComPtr<IMFSensorStream> sensorStream;
    DWORD deviceCount = 0;
    DWORD streamCount = 0;
    DWORD mediaTypeCount = 0;

    // Validate in params.
    if (nullptr == deviceSymbolicName || nullptr == profileId)
    {
        return E_INVALIDARG;
    }
    if (pinId == (UINT32)-1)
    {
        return MF_E_INVALIDSTREAMNUMBER;
    }
    if (nullptr == mediaTypeCollection)
    {
        return E_POINTER;
    }
    *mediaTypeCollection = nullptr;

    RETURN_IF_FAILED (MFCreateCollection(collection.ReleaseAndGetAddressOf()));

    // Create the SensorGroup for our device name.  This device name
    // can be a single physical device name or it can be a multi-device
    // group of devices.  In either case, MFCreateSensorGroup will create
    // a non-activated snapshot of the device(s).
    RETURN_IF_FAILED (MFCreateSensorGroup(deviceSymbolicName, &sensorGroup));
    RETURN_IF_FAILED (sensorGroup.As(service.ReleaseAndGetAddressOf()));

    // Now check if they have a profile collection.
    RETURN_IF_FAILED (service->GetService(GUID_NULL, 
                          IID_PPV_ARGS(profileCollection.ReleaseAndGetAddressOf())));

    if (profileCollection->GetProfileCount() != 0)
    {
        // If they published profiles, but we can't find the specific
        // profile, it means this camera doesn't support that scenario
        // so we should return an empty collection of media types to
        // indicate no support.
        if (FAILED(profileCollection->FindProfile(profileId, 
                       profile.ReleaseAndGetAddressOf())))
        {
            *mediaTypeCollection = collection.Detach();
            return S_OK;
        }
    }

    // If profiles are not supported, then ALL media types are
    // supported.  And we can indicate that by keeping the
    // profile null.  So we have to walk the sensor stream
    // but that means we have to find the sensor stream for
    // the pinId.
    RETURN_IF_FAILED (sensorGroup->GetSensorDeviceCount(&deviceCount));
    for (DWORD deviceIdx = 0; deviceIdx < deviceCount && 
                              sensorStream.Get() == nullptr; deviceIdx++)
    {
        RETURN_IF_FAILED (sensorGroup->GetSensorDevice(deviceIdx, 
                              sensorDevice.ReleaseAndGetAddressOf()));

        RETURN_IF_FAILED (sensorDevice->GetStreamAttributesCount(MFSensorStreamType_Output, 
                              &streamCount));
        
        for (DWORD streamIdx = 0; streamIdx < streamCount; streamIdx++)
        {
            RETURN_IF_FAILED (sensorDevice->GetStreamAttributes(
                                  MFSensorStreamType_Output, 
                                  streamIdx, 
                                  &streamAttributes));

            if (MFGetAttributesUINT32(streamAttributes, 
                                      MF_DEVICESTREAM_STREAM_ID, 
                                      (UINT32) -1) == pinId)
            {
                RETURN_IF_FAILED (streamAttributes.As(sensorStream.ReleaseAndGetAddressOf()));
                break;
            }
        }
    }

    // If we didn't find a sensorStream for the PinId, then we
    // were given bad data....
    if (sensorStream.Get() == nullptr)
    {
        return MF_E_INVALIDSTREAMNUMBER;
    }
    RETURN_IF_FAILED (sensorStream->GetMediaTypeCount(&mediaTypeCount));
    for (DWORD mediaTypeIdx = 0; mediaTypeIdx < mediaTypeCount; mediaTypeIdx++)
    {
        ComPtr<IMFMediaType> mediaType;

        RETURN_IF_FAILED (sensorStream->GetMediaType(mediaTypeIdx, 
                                                     mediaType.ReleaseAndGetAddressOf()));
        if (profile.Get() != nullptr)
        {
            BOOL supported = FALSE;

            RETURN_IF_FAILED (profile->IsMediaTypeSupported(pinId, 
                                                            mediaType.Get(),
                                                             &supported));
            if (supported)
            {
                RETURN_IF_FAILED (collection->AddElement(mediaType.Get()));
            }
        }
        else
        {
            RETURN_IF_FAILED (collection->AddElement(mediaType.Get()));
        }
    }

    *mediaTypeCollection = collection.Detach();

    return S_OK;
}

specifikace profilu kamery v2