Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Dieser Artikel enthält Informationen zur Implementierung einer benutzerdefinierten Medienquelle innerhalb der Frame Server-Architektur.
AV Stream- und benutzerdefinierte Medienquellenoptionen
Bei der Entscheidung, wie Videoaufnahmestream-Unterstützung innerhalb der Frame Server-Architektur bereitgestellt werden soll, gibt es zwei Hauptoptionen: AV Stream und benutzerdefinierte Medienquelle.
Das AV Stream-Modell ist das Standardkameratreibermodell mit einem AV Stream Miniport-Treiber (Kernelmodustreiber). In der Regel fallen AV Stream-Treiber in zwei Hauptkategorien: MIPI-basierte Treiber und USB-Videoklassentreiber.
Für die Option "Benutzerdefinierte Medienquelle" kann das Treibermodell vollständig benutzerdefinierte (proprietäre) sein oder auf einer nicht herkömmlichen Kameraquelle (z. B. Datei oder Netzwerkquellen) basieren.
AV Stream-Treiber
Der Hauptvorteil eines AV Stream-Treiberansatzes besteht darin, dass die PnP- und Power Management/Geräteverwaltung bereits vom AV Stream-Framework behandelt wird.
Es bedeutet jedoch auch, dass die zugrunde liegende Quelle ein physisches Gerät mit einem Kernelmodustreiber sein muss, um mit der Hardware zu interfaceieren. Für UVC-Geräte wird ein Windows UVC 1.5-Klassentreiber bereitgestellt, sodass die Geräte lediglich ihre Firmware implementieren müssen.
Für MIPI-basierte Geräte muss der Anbieter einen eigenen AV Stream Miniport-Treiber implementieren.
Benutzerdefinierte Medienquelle
Für Quellen, deren Gerätetreiber bereits verfügbar ist (aber kein AV Stream Miniport-Treiber) oder Quellen, die nicht herkömmliche Kameraaufnahme verwenden, ist ein AV Stream-Treiber möglicherweise nicht geeignet. Eine über das Netzwerk verbundene IP-Kamera würde z. B. nicht in ein AV Stream-Treibermodell passen.
In solchen Situationen wäre eine benutzerdefinierte Medienquelle, die das Frame Server-Modell verwendet, eine Alternative.
| Funktionen | Benutzerdefinierte Medienquelle | AV Stream-Treiber |
|---|---|---|
| PnP und Power Management | Muss vom Quell- und/oder Stubtreiber implementiert werden. | Bereitgestellt vom AV Stream-Framework |
| Benutzermodus-Plug-In | Nicht verfügbar. Eine benutzerdefinierte Medienquelle integriert die für OEM/IHV spezifische Benutzermodus-Logik. | DMFT, Platform DMFT und MFT0 für Legacyimplementierung |
| Sensorgruppe | Unterstützt | Unterstützt |
| Kameraprofil V2 | Unterstützt | Unterstützt |
| Kameraprofil V1 | Nicht unterstützt | Unterstützt |
Anforderungen für benutzerdefinierte Medienquellen
Mit der Einführung des Windows Camera Frame Server -Diensts (als Frame Server bezeichnet) kann dies über eine benutzerdefinierte Medienquelle erreicht werden. Dies erfordert zwei Hauptkomponenten:
Ein Treiberpaket mit einem stubbed-Treiber zum Registrieren/Aktivieren einer Kamerageräteschnittstelle.
Eine COM-DLL, die die benutzerdefinierte Medienquelle hosten soll.
Die erste Anforderung ist für zwei Zwecke erforderlich:
Ein Überprüfungsprozess, um sicherzustellen, dass die benutzerdefinierte Medienquelle über einen vertrauenswürdigen Prozess installiert wird (das Treiberpaket erfordert WHQL-Zertifizierung).
Unterstützung für die standardmäßige PnP-Aufzählung und Erkennung der "Kamera".
Sicherheit
Die benutzerdefinierte Medienquelle für FrameServer unterscheidet sich von der generischen benutzerdefinierten Medienquelle in Bezug auf die Sicherheit auf folgende Weise:
Frame Server Custom Media Source wird als lokaler Dienst ausgeführt (nicht zu verwechseln mit dem lokalen System; Der lokale Dienst ist ein Konto mit niedriger Privilegierten auf Windows-Computern.
Frame Server Custom Media Source wird in Sitzung 0 (Systemdienstsitzung) ausgeführt und kann nicht mit dem Benutzerdesktop interagieren.
Aufgrund dieser Einschränkungen darf Frame Server Custom Media Sources weder versuchen, auf geschützte Teile des Dateisystems noch auf die Registrierung zuzugreifen. Im Allgemeinen ist der Lesezugriff zulässig, der Schreibzugriff ist jedoch nicht möglich.
Leistung
Im Rahmen des Frame Server-Modells gibt es zwei Fälle, in denen benutzerdefinierte Medienquellen vom Frameserver instanziiert werden:
Während der Generierung und Veröffentlichung der Sensorgruppen.
Während der Aktivierung der "Kamera"
Die Sensorgruppengenerierung erfolgt in der Regel während der Geräteinstallation und/oder des Stromzyklus. Daher wird dringend empfohlen, dass benutzerdefinierte Medienquellen während der Erstellung eine erhebliche Verarbeitung vermeiden und solche Aktivitäten auf die IMFMediaSource::Start-Funktion zurückstellen. Die Sensorgruppengenerierung versucht nicht, die benutzerdefinierte Medienquelle zu starten, sondern lediglich die verschiedenen verfügbaren Datenströme/Medientypen und Quell-/Stream-Attributinformationen abzufragen.
Stub-Treiber
Es gibt zwei Mindestanforderungen für das Treiberpaket und den Stubtreiber.
Der Stubtreiber kann entweder mit dem WDF (UMDF oder KMDF) oder dem WDM-Treibermodell geschrieben werden.
Die Treiberanforderungen sind:
- Registrieren Sie ihre "Kamera" (die Benutzerdefinierte Medienquelle)-Geräteschnittstelle unter der Kategorie KSCATEGORY_VIDEO_CAMERA , damit sie aufgezählt werden kann.
Hinweis
Um die Enumeration von Legacy-DirectShow-Anwendungen zuzulassen, muss sich Ihr Treiber auch unter dem KSCATEGORY_VIDEO und KSCATEGORY_CAPTURE registrieren.
- Fügen Sie einen Registrierungseintrag unter dem Geräteschnittstellen-Knoten hinzu (verwenden Sie die AddReg-Direktive im Abschnitt DDInstall.Interface Ihrer Treiber-INF) , die die CoCreate-fähige CLSID Ihres COM-Objekts für die benutzerdefinierte Medienquelle deklariert. Dies muss mithilfe des folgenden Registrierungswertnamens hinzugefügt werden: CustomCaptureSourceClsid.
Auf diese Weise kann die "Kamera"-Quelle von Anwendungen ermittelt werden und informiert den Frame Server-Dienst, den Aktivierungsaufruf abzufangen und an die coCreated Custom Media Source umzuleiten.
Beispiel-INF
Das folgende Beispiel zeigt einen typischen INF für einen benutzerdefinierten Medienquellen-Stubtreiber:
;/*++
;
;Module Name:
; SimpleMediaSourceDriver.INF
;
;Abstract:
; INF file for installing the Usermode SimpleMediaSourceDriver Driver
;
;Installation Notes:
; Using Devcon: Type "devcon install SimpleMediaSourceDriver.inf root\SimpleMediaSource" to install
;
;--*/
[Version]
Signature="$WINDOWS NT$"
Class=Sample
ClassGuid={5EF7C2A5-FF8F-4C1F-81A7-43D3CBADDC98}
Provider=%ProviderString%
DriverVer=01/28/2016,0.10.1234
CatalogFile=SimpleMediaSourceDriver.cat
PnpLockdown=1
[DestinationDirs]
DefaultDestDir = 13
UMDriverCopy=13 ; copy to DriverStore
CustomCaptureSourceCopy=13
; ================= Class section =====================
[ClassInstall32]
Addreg=SimpleMediaSourceClassReg
[SimpleMediaSourceClassReg]
HKR,,,0,%ClassName%
HKR,,Icon,,-24
[SourceDisksNames]
1 = %DiskId1%,,,""
[SourceDisksFiles]
SimpleMediaSourceDriver.dll = 1,,
SimpleMediaSource.dll = 1,,
;*****************************************
; SimpleMFSource Install Section
;*****************************************
[Manufacturer]
%StdMfg%=Standard,NTamd64.10.0...25326
[Standard.NTamd64.10.0...25326]
%SimpleMediaSource.DeviceDesc%=SimpleMediaSourceWin11, root\SimpleMediaSource
;---------------- copy files
[SimpleMediaSourceWin11.NT]
Include=wudfrd.inf
Needs=WUDFRD.NT
CopyFiles=UMDriverCopy, CustomCaptureSourceCopy
AddReg = CustomCaptureSource.ComRegistration
[SimpleMediaSourceWin11.NT.Interfaces]
AddInterface = %KSCATEGORY_VIDEO_CAMERA%, %CustomCaptureSource.ReferenceString%, CustomCaptureSourceInterface
AddInterface = %KSCATEGORY_VIDEO%, %CustomCaptureSource.ReferenceString%, CustomCaptureSourceInterface
AddInterface = %KSCATEGORY_CAPTURE%, %CustomCaptureSource.ReferenceString%, CustomCaptureSourceInterface
[CustomCaptureSourceInterface]
AddReg = CustomCaptureSourceInterface.AddReg, CustomCaptureSource.ComRegistration
[CustomCaptureSourceInterface.AddReg]
HKR,,CLSID,,%ProxyVCap.CLSID%
HKR,,CustomCaptureSourceClsid,,%CustomCaptureSource.CLSID%
HKR,,FriendlyName,,%CustomCaptureSource.Desc%
[CustomCaptureSource.ComRegistration]
HKR,Classes\CLSID\%CustomCaptureSource.CLSID%,,,%CustomCaptureSource.Desc%
HKR,Classes\CLSID\%CustomCaptureSource.CLSID%\InprocServer32,,%REG_EXPAND_SZ%,%CustomCaptureSource.Location%
HKR,Classes\CLSID\%CustomCaptureSource.CLSID%\InprocServer32,ThreadingModel,,Both
[UMDriverCopy]
SimpleMediaSourceDriver.dll,,,0x00004000 ; COPYFLG_IN_USE_RENAME
[CustomCaptureSourceCopy]
SimpleMediaSource.dll,,,0x00004000 ; COPYFLG_IN_USE_RENAME
;-------------- Service installation
[SimpleMediaSourceWin11.NT.Services]
Include=wudfrd.inf
Needs=WUDFRD.NT.Services
;-------------- WDF specific section -------------
[SimpleMediaSourceWin11.NT.Wdf]
UmdfService=SimpleMediaSource, SimpleMediaSource_Install
UmdfServiceOrder=SimpleMediaSource
[SimpleMediaSource_Install]
UmdfLibraryVersion=$UMDFVERSION$
ServiceBinary=%13%\SimpleMediaSourceDriver.dll
[Strings]
ProviderString = "Microsoft Corporation"
StdMfg = "(Standard system devices)"
DiskId1 = "SimpleMediaSource Disk \#1"
SimpleMediaSource.DeviceDesc = "SimpleMediaSource Capture Source" ; what you will see under SimpleMediaSource dummy devices
ClassName = "SimpleMediaSource dummy devices" ; device type this driver will install as in device manager
WudfRdDisplayName="Windows Driver Foundation - User-mode Driver Framework Reflector"
KSCATEGORY_VIDEO_CAMERA = "{E5323777-F976-4f5b-9B55-B94699C46E44}"
KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
KSCATEGORY_VIDEO="{6994AD05-93EF-11D0-A3CC-00A0C9223196}"
ProxyVCap.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
CustomCaptureSource.Desc = "SimpleMediaSource Source"
CustomCaptureSource.ReferenceString = "CustomCameraSource"
CustomCaptureSource.CLSID = "{9812588D-5CE9-4E4C-ABC1-049138D10DCE}"
CustomCaptureSource.Location = "%13%\SimpleMediaSource.dll"
CustomCaptureSource.Binary = "SimpleMediaSource.dll"
REG_EXPAND_SZ = 0x00020000
Die obige benutzerdefinierte Medienquelle registriert sich unter KSCATEGORY_VIDEO, KSCATEGORY_CAPTURE und KSCATEGORY_VIDEO_CAMERA , um sicherzustellen, dass die "Kamera" von allen UWP- und Nicht-UWP-Apps gefunden werden kann, die nach einer STANDARD-RGB-Kamera suchen.
Wenn die benutzerdefinierte Medienquelle auch Nicht-RGB-Streams (IR, Depth usw.) verfügbar macht, kann sie sich optional auch unter dem KSCATEGORY_SENSOR_CAMERA registrieren.
Hinweis
Die meisten USB-basierten Webcams machen YUY2- und MJPG-Formate verfügbar. Aufgrund dieses Verhaltens werden viele ältere DirectShow-Anwendungen mit der Annahme geschrieben, dass YUY2/MJPG verfügbar ist. Um die Kompatibilität mit solchen Anwendungen zu gewährleisten, wird empfohlen, dass der YUY2-Medientyp von Ihrer benutzerdefinierten Medienquelle bereitgestellt wird, falls eine Kompatibilität mit älteren Apps gewünscht ist.
Stub-Treiberimplementierung
Zusätzlich zum INF muss der Treiberstub auch die Kamerageräteschnittstellen registrieren und aktivieren. Dies erfolgt in der Regel während des DRIVER_ADD_DEVICE Vorgangs.
Siehe die DRIVER_ADD_DEVICE Rückruffunktion für WDM-basierte Treiber und die WdfDriverCreate-Funktion für UMDF/KMDF-Treiber.
Es folgt ein Codestück eines UMDF-Treiber-Stubs, der diesen Vorgang behandelt.
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
DriverEntry initializes the driver and is the first routine called by the
system after the driver is loaded. DriverEntry specifies the other entry
points in the function driver, such as EvtDevice and DriverUnload.
Parameters Description:
DriverObject - represents the instance of the function driver that is loaded
into memory. DriverEntry must initialize members of DriverObject before it
returns to the caller. DriverObject is allocated by the system before the
driver is loaded, and it is released by the system after the system unloads
the function driver from memory.
RegistryPath - represents the driver specific path in the Registry.
The function driver can use the path to store driver related data between
reboots. The path does not store hardware instance specific data.
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise.
--*/
{
WDF_DRIVER_CONFIG config;
NTSTATUS status;
WDF_DRIVER_CONFIG_INIT(&config,
EchoEvtDeviceAdd
);
status = WdfDriverCreate(DriverObject,
RegistryPath,
WDF_NO_OBJECT_ATTRIBUTES,
&config,
WDF_NO_HANDLE);
if (!NT_SUCCESS(status)) {
KdPrint(("Error: WdfDriverCreate failed 0x%x\n", status));
return status;
}
// ...
return status;
}
NTSTATUS
EchoEvtDeviceAdd(
IN WDFDRIVER Driver,
IN PWDFDEVICE_INIT DeviceInit
)
/*++
Routine Description:
EvtDeviceAdd is called by the framework in response to AddDevice
call from the PnP manager. We create and initialize a device object to
represent a new instance of the device.
Arguments:
Driver - Handle to a framework driver object created in DriverEntry
DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
UNREFERENCED_PARAMETER(Driver);
KdPrint(("Enter EchoEvtDeviceAdd\n"));
status = EchoDeviceCreate(DeviceInit);
return status;
}
NTSTATUS
EchoDeviceCreate(
PWDFDEVICE_INIT DeviceInit
/*++
Routine Description:
Worker routine called to create a device and its software resources.
Arguments:
DeviceInit - Pointer to an opaque init structure. Memory for this
structure will be freed by the framework when the WdfDeviceCreate
succeeds. Do not access the structure after that point.
Return Value:
NTSTATUS
--*/
{
WDF_OBJECT_ATTRIBUTES deviceAttributes;
PDEVICE_CONTEXT deviceContext;
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
WDFDEVICE device;
NTSTATUS status;
UNICODE_STRING szReference;
RtlInitUnicodeString(&szReference, L"CustomCameraSource");
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
//
// Register pnp/power callbacks so that we can start and stop the timer as the device
// gets started and stopped.
//
pnpPowerCallbacks.EvtDeviceSelfManagedIoInit = EchoEvtDeviceSelfManagedIoStart;
pnpPowerCallbacks.EvtDeviceSelfManagedIoSuspend = EchoEvtDeviceSelfManagedIoSuspend;
#pragma prefast(suppress: 28024, "Function used for both Init and Restart Callbacks")
pnpPowerCallbacks.EvtDeviceSelfManagedIoRestart = EchoEvtDeviceSelfManagedIoStart;
//
// Register the PnP and power callbacks. Power policy related callbacks will be registered
// later in SoftwareInit.
//
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
{
WDF_FILEOBJECT_CONFIG cameraFileObjectConfig;
WDF_OBJECT_ATTRIBUTES cameraFileObjectAttributes;
WDF_OBJECT_ATTRIBUTES_INIT(&cameraFileObjectAttributes);
cameraFileObjectAttributes.SynchronizationScope = WdfSynchronizationScopeNone;
WDF_FILEOBJECT_CONFIG_INIT(
&cameraFileObjectConfig,
EvtCameraDeviceFileCreate,
EvtCameraDeviceFileClose,
WDF_NO_EVENT_CALLBACK);
WdfDeviceInitSetFileObjectConfig(
DeviceInit,
&cameraFileObjectConfig,
&cameraFileObjectAttributes);
}
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);
status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
if (NT_SUCCESS(status)) {
//
// Get the device context and initialize it. WdfObjectGet_DEVICE_CONTEXT is an
// inline function generated by WDF_DECLARE_CONTEXT_TYPE macro in the
// device.h header file. This function will do the type checking and return
// the device context. If you pass a wrong object handle
// it will return NULL and assert if run under framework verifier mode.
//
deviceContext = WdfObjectGet_DEVICE_CONTEXT(device);
deviceContext->PrivateDeviceData = 0;
//
// Create a device interface so that application can find and talk
// to us.
//
status = WdfDeviceCreateDeviceInterface(
device,
&CAMERA_CATEGORY,
&szReference // ReferenceString
);
if (NT_SUCCESS(status)) {
//
// Create a device interface so that application can find and talk
// to us.
//
status = WdfDeviceCreateDeviceInterface(
device,
&CAPTURE_CATEGORY,
&szReference // ReferenceString
);
}
if (NT_SUCCESS(status)) {
//
// Create a device interface so that application can find and talk
// to us.
//
status = WdfDeviceCreateDeviceInterface(
device,
&VIDEO_CATEGORY,
&szReference // ReferenceString
);
}
if (NT_SUCCESS(status)) {
//
// Initialize the I/O Package and any Queues
//
status = EchoQueueInitialize(device);
}
}
return status;
}
PnP-Vorgang
Genau wie jede andere physische Kamera wird empfohlen, dass Ihr Stubtreiber mindestens die PnP-Vorgänge zum Aktivieren und Deaktivieren des Geräts verwaltet, wenn die zugrunde liegende Quelle entfernt/angefügt wird. Wenn Ihre benutzerdefinierte Medienquelle beispielsweise eine Netzwerkquelle verwendet (z. B. eine IP-Kamera), können Sie eine Geräteentfernung auslösen, wenn diese Netzwerkquelle nicht mehr verfügbar ist.
Dadurch wird sichergestellt, dass Anwendungen, die über die PnP-APIs auf das Hinzufügen oder Entfernen von Geräten lauschen, die richtigen Benachrichtigungen erhalten. Und stellt sicher, dass eine nicht mehr verfügbare Quelle nicht aufgezählt werden kann.
Informationen zu UMDF- und KMDF-Treibern finden Sie in der Dokumentation zur WdfDeviceSetDeviceState-Funktion .
Informationen zu WMD-Treibern finden Sie in der Dokumentation zur IoSetDeviceInterfaceState-Funktion .
Benutzerdefinierte Medienquell-DLL
Die benutzerdefinierte Medienquelle ist ein standardmäßiger INPROC-COM-Server, der die folgenden Schnittstellen implementieren muss:
Hinweis
IMFMediaSourceEx erbt von IMFMediaSource und IMFMediaSource von IMFMediaEventGenerator.
Jeder unterstützte Datenstrom in der benutzerdefinierten Medienquelle muss die folgenden Schnittstellen unterstützen:
IMFMediaEventGenerator
IMFMediaStream2
Hinweis
IMFMediaStream2 erbt von IMFMediaStream und IMFMediaStream erbt von IMFMediaEventGenerator.
Informationen zum Erstellen einer benutzerdefinierten Medienquelle finden Sie in der Dokumentation zum Schreiben einer benutzerdefinierten Medienquelle . Im restlichen Abschnitt werden die Unterschiede erläutert, die erforderlich sind, um Ihre benutzerdefinierte Medienquelle im Frame Server-Framework zu unterstützen.
IMFGetService
IMFGetService ist eine obligatorische Schnittstelle für benutzerdefinierte Frame Server-Medienquelle. IMFGetService gibt möglicherweise MF_E_UNSUPPORTED_SERVICE zurück, wenn Ihre benutzerdefinierte Medienquelle keine anderen Dienstschnittstellen verfügbar machen muss.
Das folgende Beispiel zeigt eine IMFGetService-Implementierung ohne Supportdienstschnittstellen:
_Use_decl_annotations_
IFACEMETHODIMP
SimpleMediaSource::GetService(
_In_ REFGUID guidService,
_In_ REFIID riid,
_Out_ LPVOID * ppvObject
)
{
HRESULT hr = S_OK;
auto lock = _critSec.Lock();
RETURN_IF_FAILED (_CheckShutdownRequiresLock());
if (!ppvObject)
{
return E_POINTER;
}
*ppvObject = NULL;
// We have no supported service, just return
// MF_E_UNSUPPORTED_SERVICE for all calls.
return MF_E_UNSUPPORTED_SERVICE;
}
IMFMediaEventGenerator
Wie oben gezeigt, müssen sowohl die Quelle als auch die einzelnen Datenströme innerhalb der Quelle ihre eigene IMFMediaEventGenerator-Schnittstelle unterstützen. Die gesamten Daten- und Steuerströme der MF-Pipeline vom Ursprung werden über den Ereignisgenerator gesteuert, indem bestimmte IMFMediaEvent gesendet werden.
Für die Implementierung von IMFMediaEventGenerator muss die benutzerdefinierte Medienquelle die MFCreateEventQueue-API verwenden, um eine IMFMediaEventQueue zu erstellen und alle Methoden für IMFMediaEventGenerator an das Warteschlangenobjekt weiterzuleiten:
IMFMediaEventGenerator hat die folgenden Methoden:
// IMFMediaEventGenerator
IFACEMETHOD(BeginGetEvent)(_In_ IMFAsyncCallback *pCallback, _In_ IUnknown *punkState);
IFACEMETHOD(EndGetEvent)(_In_ IMFAsyncResult *pResult, _COM_Outptr_ IMFMediaEvent **ppEvent);
IFACEMETHOD(GetEvent)(DWORD dwFlags, _Out_ IMFMediaEvent **ppEvent);
IFACEMETHOD(QueueEvent)(MediaEventType met, REFGUID guidExtendedType, HRESULT hrStatus, _In_opt_ const PROPVARIANT *pvValue);
Der folgende Code zeigt die empfohlene Implementierung der IMFMediaEventGenerator-Schnittstelle . Die Implementierung der benutzerdefinierten Medienquelle macht die IMFMediaEventGenerator-Schnittstelle verfügbar, und die Methoden für diese Schnittstelle routingen die Anforderungen an das IMFMediaEventQueue -Objekt, das während der Erstellung/Initialisierung der Medienquelle erstellt wurde.
Im folgenden Code ist _spEventQueue Objekt das IMFMediaEventQueue-Objekt , das mithilfe der Funktion MFCreateEventQueue erstellt wurde:
// IMFMediaEventGenerator methods
IFACEMETHODIMP
SimpleMediaSource::BeginGetEvent(
_In_ IMFAsyncCallback *pCallback,
_In_ IUnknown *punkState
)
{
HRESULT hr = S_OK;
auto lock = _critSec.Lock();
RETURN_IF_FAILED (_CheckShutdownRequiresLock());
RETURN_IF_FAILED (_spEventQueue->BeginGetEvent(pCallback, punkState));
return hr;
}
IFACEMETHODIMP
SimpleMediaSource::EndGetEvent(
_In_ IMFAsyncResult *pResult,
_COM_Outptr_ IMFMediaEvent **ppEvent
)
{
HRESULT hr = S_OK;
auto lock = _critSec.Lock();
RETURN_IF_FAILED (_CheckShutdownRequiresLock());
RETURN_IF_FAILED (_spEventQueue->EndGetEvent(pResult, ppEvent));
return hr;
}
IFACEMETHODIMP
SimpleMediaSource::GetEvent(
DWORD dwFlags,
_COM_Outptr_ IMFMediaEvent **ppEvent
)
{
// NOTE:
// GetEvent can block indefinitely, so we do not hold the lock.
// This requires some juggling with the event queue pointer.
HRESULT hr = S_OK;
ComPtr<IMFMediaEventQueue> spQueue;
{
auto lock = _critSec.Lock();
RETURN_IF_FAILED (_CheckShutdownRequiresLock());
spQueue = _spEventQueue;
}
// Now get the event.
RETURN_IF_FAILED (spQueue->GetEvent(dwFlags, ppEvent));
return hr;
}
IFACEMETHODIMP
SimpleMediaSource::QueueEvent(
MediaEventType eventType,
REFGUID guidExtendedType,
HRESULT hrStatus,
_In_opt_ PROPVARIANT const *pvValue
)
{
HRESULT hr = S_OK;
auto lock = _critSec.Lock();
RETURN_IF_FAILED (_CheckShutdownRequiresLock());
RETURN_IF_FAILED (_spEventQueue->QueueEventParamVar(eventType, guidExtendedType, hrStatus, pvValue));
return hr;
}
Suchen und Pause
Benutzerdefinierte Medienquellen, die über das Frame Server-Framework unterstützt werden, unterstützen keine Seek- oder Pause-Vorgänge. Ihre benutzerdefinierte Medienquelle muss keine Unterstützung für diese Vorgänge bereitstellen und darf weder das MFSourceSeeked - noch das MEStreamSeeked-Ereignis bereitstellen.
IMFMediaSource::Pause sollte MF_E_INVALID_STATE_TRANSITION zurückgeben (oder MF_E_SHUTDOWN, wenn die Quelle bereits heruntergefahren wurde).
IKsControl
IKsControl ist die Standardsteuerungsschnittstelle für alle kamerabezogenen Steuerelemente. Wenn Ihre benutzerdefinierte Medienquelle irgendwelche Kamerasteuerelemente implementiert, leitet die Pipeline die Steuerungs-I/O über die IKsControl-Schnittstelle.
Weitere Informationen finden Sie in den folgenden Dokumentationsartikeln zu den Steuerungseinstellungen:
Wenn die Steuerelemente optional sind und nicht unterstützt werden, ist der empfohlene Fehlercode HRESULT_FROM_WIN32(ERROR_SET_NOT_FOUND).
Der folgende Code ist eine Beispielimplementierung von IKsControl ohne unterstützte Steuerelemente:
// IKsControl methods
_Use_decl_annotations_
IFACEMETHODIMP
SimpleMediaSource::KsProperty(
_In_reads_bytes_(ulPropertyLength) PKSPROPERTY pProperty,
_In_ ULONG ulPropertyLength,
_Inout_updates_to_(ulDataLength, *pBytesReturned) LPVOID pPropertyData,
_In_ ULONG ulDataLength,
_Out_ ULONG* pBytesReturned
)
{
// ERROR_SET_NOT_FOUND is the standard error code returned
// by the AV Stream driver framework when a miniport
// driver does not register a handler for a KS operation.
// We want to mimic the driver behavior here if we do not
// support controls.
return HRESULT_FROM_WIN32(ERROR_SET_NOT_FOUND);
}
_Use_decl_annotations_
IFACEMETHODIMP SimpleMediaSource::KsMethod(
_In_reads_bytes_(ulMethodLength) PKSMETHOD pMethod,
_In_ ULONG ulMethodLength,
_Inout_updates_to_(ulDataLength, *pBytesReturned) LPVOID pMethodData,
_In_ ULONG ulDataLength,
_Out_ ULONG* pBytesReturned
)
{
return HRESULT_FROM_WIN32(ERROR_SET_NOT_FOUND);
}
_Use_decl_annotations_
IFACEMETHODIMP SimpleMediaSource::KsEvent(
_In_reads_bytes_opt_(ulEventLength) PKSEVENT pEvent,
_In_ ULONG ulEventLength,
_Inout_updates_to_(ulDataLength, *pBytesReturned) LPVOID pEventData,
_In_ ULONG ulDataLength,
_Out_opt_ ULONG* pBytesReturned
)
{
return HRESULT_FROM_WIN32(ERROR_SET_NOT_FOUND);
}
IMFMediaStream2
Wie in Writing a Custom Media Source erläutert, wird die IMFMediaStream2-Schnittstelle dem Framework von Ihrer benutzerdefinierten Medienquelle über ein MENewStream-Medienereignis bereitgestellt, das während der Ausführung der IMFMediaSource::Start-Methode in die Quellereigniswarteschlange eingestellt wird:
IFACEMETHODIMP
SimpleMediaSource::Start(
_In_ IMFPresentationDescriptor *pPresentationDescriptor,
_In_opt_ const GUID *pguidTimeFormat,
_In_ const PROPVARIANT *pvarStartPos
)
{
HRESULT hr = S_OK;
auto lock = _critSec.Lock();
DWORD count = 0;
PROPVARIANT startTime;
BOOL selected = false;
ComPtr<IMFStreamDescriptor> streamDesc;
DWORD streamIndex = 0;
if (pPresentationDescriptor == nullptr || pvarStartPos == nullptr)
{
return E_INVALIDARG;
}
else if (pguidTimeFormat != nullptr && *pguidTimeFormat != GUID_NULL)
{
return MF_E_UNSUPPORTED_TIME_FORMAT;
}
RETURN_IF_FAILED (_CheckShutdownRequiresLock());
if (_sourceState != SourceState::Stopped)
{
return MF_E_INVALID_STATE_TRANSITION;
}
_sourceState = SourceState::Started;
// This checks the passed in PresentationDescriptor matches the member of streams we
// have defined internally and that at least one stream is selected
RETURN_IF_FAILED (_ValidatePresentationDescriptor(pPresentationDescriptor));
RETURN_IF_FAILED (pPresentationDescriptor->GetStreamDescriptorCount(&count));
RETURN_IF_FAILED (InitPropVariantFromInt64(MFGetSystemTime(), &startTime));
// Send event that the source started. Include error code in case it failed.
RETURN_IF_FAILED (_spEventQueue->QueueEventParamVar(MESourceStarted,
GUID_NULL,
hr,
&startTime));
// We are hardcoding this to the first descriptor
// since this sample is a single stream sample. For
// multiple streams, we need to walk the list of streams
// and for each selected stream, send the MEUpdatedStream
// or MENewStream event along with the MEStreamStarted
// event.
RETURN_IF_FAILED (pPresentationDescriptor->GetStreamDescriptorByIndex(0,
&selected,
&streamDesc));
RETURN_IF_FAILED (streamDesc->GetStreamIdentifier(&streamIndex));
if (streamIndex >= NUM_STREAMS)
{
return MF_E_INVALIDSTREAMNUMBER;
}
if (selected)
{
ComPtr<IUnknown> spunkStream;
MediaEventType met = (_wasStreamPreviouslySelected ? MEUpdatedStream : MENewStream);
// Update our internal PresentationDescriptor
RETURN_IF_FAILED (_spPresentationDescriptor->SelectStream(streamIndex));
RETURN_IF_FAILED (_stream.Get()->SetStreamState(MF_STREAM_STATE_RUNNING));
RETURN_IF_FAILED (_stream.As(&spunkStream));
// Send the MEUpdatedStream/MENewStream to our source event
// queue.
RETURN_IF_FAILED (_spEventQueue->QueueEventParamUnk(met,
GUID_NULL,
S_OK,
spunkStream.Get()));
// But for our stream started (MEStreamStarted), we post to our
// stream event queue.
RETURN_IF_FAILED (_stream.Get()->QueueEvent(MEStreamStarted,
GUID_NULL,
S_OK,
&startTime));
}
_wasStreamPreviouslySelected = selected;
return hr;
}
Dies muss für jeden datenstrom erfolgen, der über den IMFPresentationDescriptor ausgewählt wurde.
Für benutzerdefinierte Medienquellen mit Videostream sollten MEEndOfStream - und MEEndOfPresentation-Ereignisse nicht gesendet werden.
Streamattribute
Alle benutzerdefinierten Medienquellendatenströme müssen die MF_DEVICESTREAM_STREAM_CATEGORY auf PINNAME_VIDEO_CAPTURE festgelegt sein. PINNAME_VIDEO_PREVIEW wird für benutzerdefinierte Medienquellen nicht unterstützt.
Hinweis
PINNAME_IMAGE, während unterstützt, wird nicht empfohlen. Um einen Datenstrom mit PINNAME_IMAGE verfügbar zu machen, muss die benutzerdefinierte Medienquelle alle Fototrigger-Steuerelemente unterstützen. Weitere Details finden Sie im Abschnitt "Photo Stream Controls " weiter unten.
MF_DEVICESTREAM_STREAM_ID ist ein obligatorisches Attribut für alle Datenströme. Es sollte ein 0-basierter Index sein. Der erste Datenstrom hat also eine ID von 0, zweiten Stream eine ID von 1 usw.
Im Folgenden sind eine Liste der empfohlenen Attribute für den Datenstrom aufgeführt:
MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES
MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES ist ein UINT32-Attribut, bei dem es sich um einen Bitmaskenwert des Datenstromtyps handelt. Es kann auf einen der folgenden Typen festgelegt werden (diese Typen sind zwar ein Bitmasken-Flag, es wird jedoch empfohlen, Quelltypen nach Möglichkeit nicht zu mischen):
| Typ | Flagge | BESCHREIBUNG |
|---|---|---|
| MFFrameSourceTypes_Color | 0x0001 | Rgb-Standardfarbstrom |
| MFFrameSourceTypes_Infrared | 0x0002 | Infrarot-Datenstrom |
| MFFrameSourceTypes_Depth | 0x0004 | Tiefenstrom |
| MFFrameSourceTypes_Bild | 0x0008 | Bildstream (nicht videountertyp, in der Regel JPEG) |
| MFFrameSourceTypes_Custom | 0x0080 | Benutzerdefinierter Streamtyp |
MF_DEVICESTREAM_FRAMESERVER_SHARED
MF_DEVICESTREAM_FRAMESERVER_SHARED ist ein UINT32-Attribut, das entweder auf 0 oder 1 festgelegt werden kann. Bei Festlegung auf "1" wird der Datenstrom vom Frameserver als "freigabefähig" markiert. Dadurch können Anwendungen den Datenstrom in einem freigegebenen Modus öffnen, auch wenn er von einer anderen App verwendet wird.
Wenn dieses Attribut nicht festgelegt ist, ermöglicht Frame Server, dass der erste nicht markierte Datenstrom freigegeben werden kann (wenn die benutzerdefinierte Medienquelle nur einen Datenstrom aufweist, wird dieser Datenstrom als freigegeben markiert).
Wenn dieses Attribut auf 0 festgelegt ist, blockiert Frame Server den Datenstrom aus freigegebenen Apps. Wenn die benutzerdefinierte Medienquelle alle Datenströme mit diesem Attribut auf 0 kennzeichnet, kann keine freigegebene Anwendung die Quelle initialisieren.
Zuweisung von Beispielen
Alle Medienframes müssen als IMFSample erstellt werden. Benutzerdefinierte Medienquellen müssen die MFCreateSample-Funktion verwenden, um eine Instanz von IMFSample zuzuweisen und die AddBuffer-Methode zum Hinzufügen von Medienpuffern zu verwenden.
Jedes IMFSample muss die Beispielzeit und die Beispieldauer festgelegt haben. Alle Beispielzeitstempel müssen auf QPC-Zeit (QueryPerformanceCounter) basieren.
Es wird empfohlen, dass benutzerdefinierte Medienquellen nach Möglichkeit die MFGetSystemTime-Funktion verwenden. Diese Funktion ist ein Wrapper um QueryPerformanceCounter und konvertiert die QPC-Ticks in 100-Nanosekundeneinheiten.
Benutzerdefinierte Medienquellen verwenden möglicherweise eine interne Uhr, aber alle Zeitstempel müssen basierend auf dem aktuellen QPC mit 100-Nanosekunden-Einheiten korreliert werden.
Medienpuffer
Alle dem IMFSample hinzugefügten Medienpuffer müssen die standardmäßigen MF-Pufferzuweisungsfunktionen verwenden. Benutzerdefinierte Medienquellen dürfen keine eigenen IMFMediaBuffer-Schnittstellen implementieren oder versuchen, Medienpuffer direkt zuzuweisen (z. B. "new/malloc/VirtualAlloc" usw., dürfen nicht für Framedaten verwendet werden).
Verwenden Sie eine der folgenden APIs, um Medienframes zuzuweisen:
MFCreateMemoryBuffer und MFCreateAlignedMemoryBuffer sollten für Medien-Daten ohne Stride-Ausrichtung verwendet werden. In der Regel handelt es sich hierbei um benutzerdefinierte Untertypen oder komprimierte Untertypen (z. B. H264/HEVC/MJPG).
Für bekannte nicht komprimierte Medientypen (z. B. YUY2, NV12 usw.) mit Systemspeicher empfiehlt es sich, MFCreate2DMediaBuffer zu verwenden.
Für die Verwendung von DX-Oberflächen (für gpubeschleunigte Vorgänge wie Rendering und/oder Codierung) sollte MFCreateDXGISurfaceBuffer verwendet werden.
MFCreateDXGISurfaceBuffer erstellt nicht die DX-Oberfläche. Die Oberfläche wird mithilfe des DXGI-Managers erstellt, der über die IMFMediaSourceEx::SetD3DManager-Methode an die Medienquelle übergeben wird.
Der IMFDXGIDeviceManager::OpenDeviceHandle stellt das Handle bereit, das dem ausgewählten D3D-Gerät zugeordnet ist. Die ID3D11Device-Schnittstelle kann dann mithilfe der IMFDXGIDeviceManager::GetVideoService-Methode abgerufen werden.
Unabhängig davon, welcher Puffertyp verwendet wird, muss das erstellte IMFSample über das MEMediaSample-Ereignis im IMFMediaEventGenerator des Mediendatenstroms für die Pipeline bereitgestellt werden.
Obwohl es möglich ist, den gleichen IMFMediaEventQueue sowohl für die benutzerdefinierte Medienquelle als auch für die zugrunde liegende Sammlung von IMFMediaStream zu verwenden, sollte darauf hingewiesen werden, dass dies zur Serialisierung der Medienquellenereignisse und Streamereignisse (einschließlich des Medienflusses) führt. Für Quellen mit mehreren Datenströmen ist dies nicht wünschenswert.
Der folgende Codeausschnitt zeigt eine Beispielimplementierung des Medienstreams:
IFACEMETHODIMP
SimpleMediaStream::RequestSample(
_In_ IUnknown *pToken
)
{
HRESULT hr = S_OK;
auto lock = _critSec.Lock();
ComPtr<IMFSample> sample;
ComPtr<IMFMediaBuffer> outputBuffer;
LONG pitch = IMAGE_ROW_SIZE_BYTES;
BYTE *bufferStart = nullptr; // not used
DWORD bufferLength = 0;
BYTE *pbuf = nullptr;
ComPtr<IMF2DBuffer2> buffer2D;
RETURN_IF_FAILED (_CheckShutdownRequiresLock());
RETURN_IF_FAILED (MFCreateSample(&sample));
RETURN_IF_FAILED (MFCreate2DMediaBuffer(NUM_IMAGE_COLS,
NUM_IMAGE_ROWS,
D3DFMT_X8R8G8B8,
false,
&outputBuffer));
RETURN_IF_FAILED (outputBuffer.As(&buffer2D));
RETURN_IF_FAILED (buffer2D->Lock2DSize(MF2DBuffer_LockFlags_Write,
&pbuf,
&pitch,
&bufferStart,
&bufferLength));
RETURN_IF_FAILED (WriteSampleData(pbuf, pitch, bufferLength));
RETURN_IF_FAILED (buffer2D->Unlock2D());
RETURN_IF_FAILED (sample->AddBuffer(outputBuffer.Get()));
RETURN_IF_FAILED (sample->SetSampleTime(MFGetSystemTime()));
RETURN_IF_FAILED (sample->SetSampleDuration(333333));
if (pToken != nullptr)
{
RETURN_IF_FAILED (sample->SetUnknown(MFSampleExtension_Token, pToken));
}
RETURN_IF_FAILED (_spEventQueue->QueueEventParamUnk(MEMediaSample,
GUID_NULL,
S_OK,
sample.Get()));
return hr;
}
Benutzerdefinierte Media Source-Erweiterung zur Exponierung von IMFActivate (verfügbar in Windows 10, Version 1809)
Zusätzlich zur obigen Liste der Schnittstellen, die für eine benutzerdefinierte Medienquelle unterstützt werden müssen, besteht eine der Einschränkungen, die durch den Vorgang "Benutzerdefinierte Medienquelle" innerhalb der Frame Server-Architektur auferlegt werden, dass nur eine Instanz des UMDF-Treibers "aktiviert" über die Pipeline vorhanden sein kann.
Wenn Sie beispielsweise über ein physisches Gerät verfügen, das zusätzlich zu seinem Nicht-AV-Stream-Treiberpaket einen UMDF-Stubtreiber installiert, und Sie mehr als eines dieser physischen Geräte an einen Computer anschließen, erhält zwar jede Instanz des UMDF-Treibers einen eindeutigen symbolischen Linknamen, aber der Aktivierungspfad für die benutzerdefinierte Medienquelle kann den symbolischen Linknamen, der bei der Erstellungszeit der benutzerdefinierten Medienquelle zugeordnet wird, nicht kommunizieren.
Benutzerdefinierte Medienquelle sucht möglicherweise nach dem Standardattribut MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK im Attributspeicher der benutzerdefinierten Medienquelle (der attributspeicher, der von der benutzerdefinierten Medienquelle über die IMFMediaSourceEx::GetSourceAttributes-Methode zurückgegeben wird), wenn IMFMediaSource::Start aufgerufen wird.
Dies kann jedoch zu einer höheren Startlatenz führen, da die Erfassung der Hardware-Ressourcen für den Startzeitpunkt und nicht für den Erstellungs-/Initialisierungszeitpunkt aufgeschoben wird.
Aus diesem Fall können in Windows 10, Version 1809, benutzerdefinierte Medienquellen optional eine IMFActivate-Schnittstelle verfügbar machen.
Hinweis
IMFActivate erbt von IMFAttributes.
IMFActivate
Wenn der COM-Server für die benutzerdefinierte Medienquelle DIE IMFActivate-Schnittstelle unterstützt, werden die Geräteinitialisierungsinformationen über die vom IMFActivate geerbten IMFAttribute an den COM-Server bereitgestellt. Wenn also das IMFActivate::ActivateObject aufgerufen wird, enthält der Attributspeicher des IMFActivate den symbolischen Verknüpfungsnamen des UMDF-Stubtreibers und alle anderen Konfigurationseinstellungen, die von der Pipeline/Anwendung zum Zeitpunkt der Quellerstellung/Initialisierung bereitgestellt werden.
Die benutzerdefinierte Medienquelle sollte diese Methode verwenden, um alle benötigten Hardwareressourcen zu erlangen.
Hinweis
Wenn der Erwerb von Hardwareressourcen mehr als 200 Millisekunden benötigt, wird empfohlen, eine Hardwareressource asynchron zu erwerben. Die Aktivierung der benutzerdefinierten Medienquelle sollte nicht durch die Hardware-Ressourcenakquisition blockiert werden. Stattdessen sollte der IMFMediaSource::Start-Vorgang für den Hardwareressourcenerwerb serialisiert werden.
Die beiden anderen Methoden, die von IMFActivate, DetachObject und ShutdownObject verfügbar gemacht werden, müssen E_NOTIMPL zurückgeben.
Die benutzerdefinierte Medienquelle kann die IMFActivate- und die IMFAttributes-Schnittstelle innerhalb desselben COM-Objekts wie die IMFMediaSource implementieren. Wenn dies der Fall ist, wird empfohlen, dass IMFMediaSourceEx::GetSourceAttributes dieselbe IMFAttributes-Schnittstelle wie die von IMFActivate zurückgibt.
Wenn die benutzerdefinierte Medienquelle IMFActivate und IMFAttributes nicht mit demselben Objekt implementiert, muss die benutzerdefinierte Medienquelle alle Attribute, die im IMFActivate-Attributspeicher festgelegt sind, in den Attributspeicher der benutzerdefinierten Medienquelle kopieren.
Codierter Kameradatenstrom
Eine benutzerdefinierte Medienquelle kann komprimierte Medientypen (HEVC- oder H264-Elementardatenströme) verfügbar machen, und die Betriebssystempipeline unterstützt vollständig die Quelle und Konfiguration der Codierungsparameter für die benutzerdefinierte Medienquelle (die Codierungsparameter werden über die ICodecAPI kommuniziert, die als IKsControl::KsProperty-Aufruf weitergeleitet wird):
// IKsControl methods
_Use_decl_annotations_
IFACEMETHODIMP
SimpleMediaSource::KsProperty(
_In_reads_bytes_(ulPropertyLength) PKSPROPERTY pProperty,
_In_ ULONG ulPropertyLength,
_Inout_updates_to_(ulDataLength, *pBytesReturned) LPVOID pPropertyData,
_In_ ULONG ulDataLength,
_Out_ ULONG* pBytesReturned
);
Die an die IKsControl::KsProperty-Methode übergebene KSPROPERTY-Struktur weist die folgenden Informationen auf:
KSPROPERTY.Set = Encoder Property GUID
KSPROPERTY.Id = 0
KSPROPERTY.Flags = (KSPROPERTY_TYPE_SET or KSPROPERTY_TYPE_GET)
Dabei ist die GUID der Encoder-Eigenschaft die Liste der verfügbaren Eigenschaften, die in Codec-API-Eigenschaften definiert sind.
Die Nutzlast der Encoder-Eigenschaft wird über das pPropertyData-Feld der oben deklarierten KsProperty-Methode übergeben.
Anforderungen der Aufnahme-Engine
Während codierte Quellen von Frame Server vollständig unterstützt werden, erzwingt das clientseitige Aufnahmemodul (IMFCaptureEngine), das vom Windows.Media.Capture.MediaCapture-Objekt verwendet wird, zusätzliche Anforderungen:
Der Stream muss entweder vollständig kodiert (HEVC oder H264) oder vollständig unkomprimiert sein (in diesem Kontext wird MJPG als unkomprimiert behandelt).
Es muss mindestens ein nicht komprimierter Datenstrom verfügbar sein.
Hinweis
Diese Anforderungen sind zusätzlich zu den anforderungen für die benutzerdefinierte Medienquelle aufgeführt, die in diesem Artikel beschrieben sind. Die Anforderungen des Aufnahmemoduls werden jedoch nur erzwungen, wenn die Clientanwendung die benutzerdefinierte Medienquelle über die IMFCaptureEngine - oder Windows.Media.Capture.MediaCapture-API verwendet.
Kameraprofile (verfügbar in Windows 10, Version 1803 und höher)
Kameraprofilunterstützung ist für benutzerdefinierte Medienquellen verfügbar. Der empfohlene Mechanismus besteht darin, das Profil über das MF_DEVICEMFT_SENSORPROFILE_COLLECTION-Attribut aus dem Quellattribut (IMFMediaSourceEx::GetSourceAttributes) zu veröffentlichen.
Das attribut MF_DEVICEMFT_SENSORPROFILE_COLLECTION ist ein IUnknown der IMFSensorProfileCollection-Schnittstelle . IMFSensorProfileCollection kann mithilfe der FUNKTION MFCreateSensorProfileCollection abgerufen werden:
IFACEMETHODIMP
SimpleMediaSource::GetSourceAttributes(
_COM_Outptr_ IMFAttributes** sourceAttributes
)
{
HRESULT hr = S_OK;
auto lock = _critSec.Lock();
if (nullptr == sourceAttributes)
{
return E_POINTER;
}
RETURN_IF_FAILED (_CheckShutdownRequiresLock());
*sourceAttributes = nullptr;
if (_spAttributes.Get() == nullptr)
{
ComPtr<IMFSensorProfileCollection> profileCollection;
ComPtr<IMFSensorProfile> profile;
// Create our source attribute store
RETURN_IF_FAILED (MFCreateAttributes(_spAttributes.GetAddressOf(), 1));
// Create an empty profile collection
RETURN_IF_FAILED (MFCreateSensorProfileCollection(&profileCollection));
// In this example since we have just one stream, we only have one
// pin to add: Pin0
// 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,
profile.ReleaseAndGetAddressOf()));
RETURN_IF_FAILED (profile->AddProfileFilter(0, L"((RES==;FRT<=30,1;SUT==))"));
RETURN_IF_FAILED (profileCollection->AddProfile(profile.Get()));
// High Frame Rate profile will only allow >=60fps
RETURN_IF_FAILED (MFCreateSensorProfile(KSCAMERAPROFILE_HighFrameRate, 0, nullptr,
profile.ReleaseAndGetAddressOf()));
RETURN_IF_FAILED (profile->AddProfileFilter(0, L"((RES==;FRT>=60,1;SUT==))"));
RETURN_IF_FAILED (profileCollection->AddProfile(profile.Get()));
// See the profile collection to the attribute store of the IMFTransform
RETURN_IF_FAILED (_spAttributes->SetUnknown(MF_DEVICEMFT_SENSORPROFILE_COLLECTION,
profileCollection.Get()));
}
return _spAttributes.CopyTo(sourceAttributes);
}
Gesichtsauthentifizierungsprofil
Wenn die benutzerdefinierte Medienquelle für die Unterstützung der Windows Hello-Gesichtserkennung konzipiert ist, empfiehlt es sich, ein Gesichtsauthentifizierungsprofil zu veröffentlichen. Die Anforderungen eines Gesichtsauthentifizierungsprofils sind:
Das DDI-Steuerelement für die Gesichtsauthentifizierung muss in einem einzelnen IR-Datenstrom unterstützt werden. Weitere Informationen finden Sie unter KSPROPERTY_CAMERACONTROL_EXTENDED_FACEAUTH_MODE.
Der IR-Stream muss mindestens 340 x 340 bei 15 fps sein. Das Format muss entweder L8, NV12 oder MJPG mit L8-Komprimierung gekennzeichnet sein.
Der RGB-Stream muss mindestens 480 x 480 bei 7,5 fps betragen (dies ist nur erforderlich, wenn die Multispectrum-Authentifizierung erzwungen wird).
Das Gesichtsauthentifizierungsprofil muss über die Profil-ID von: KSCAMERAPROFILE_FaceAuth_Mode,0 verfügen.
Wir empfehlen, dass das Face Authentication Profile nur einen Medientyp für jeden der IR- und RGB-Datenströme bereitstellt.
Fotostream-Steuerelemente
Wenn unabhängige Fotostreams verfügbar gemacht werden, indem einer derMF_DEVICESTREAM_STREAM_CATEGORY des Datenstroms als PINNAME_IMAGE markiert wird, ist ein Datenstrom mit der Datenstromkategorie PINNAME_VIDEO_CAPTURE erforderlich (z. B. ein einzelner Datenstrom, der nur die PINNAME_IMAGE verfügbar macht, keine gültige Medienquelle ist).
Über IKsControl muss der PROPSETID_VIDCAP_VIDEOCONTROL Eigenschaftensatz unterstützt werden. Weitere Informationen finden Sie unter Videosteuerelementeigenschaften.