Exemples de code d’encodeur
Les exemples de code suivants sont basés sur l’exemple de pilote de matériel simulé AVStream (AVSHwS). Ils illustrent les éléments suivants :
Comment spécifier les débits binaires pris en charge par l’encodeur
Comment spécifier les modes d’encodage de débit binaire pris en charge par un encodeur
Comment spécifier des valeurs de métadonnées au moment de l’exécution sous la clé de Registre Paramètres de l’appareil d’encodeur\Fonctionnalités
Implémentation des débits binaires pris en charge
Les extraits de code suivants montrent comment implémenter la prise en charge de la propriété ENCAPIPARAM_BITRATE . Utilisez une structure de KSPROPERTY_STEPPING_LONG pour spécifier une granularité pas à pas de 400 bits par seconde (bps) avec une limite inférieure de 400 bps et une limite supérieure de 4 000 000 bps.
const KSPROPERTY_STEPPING_LONG BitRateRanges [] = {
{
400,
0,
400,
4000000
}
};
Si vous accédez à la page de propriétés du filtre de l’encodeur en cliquant avec le bouton droit sur le filtre dans un outil tel que GraphEdit, vous verrez la barre du curseur Débit binaire où ces valeurs sont utilisées.
Ensuite, spécifiez le débit d’encodage par défaut du filtre d’encodeur lorsqu’un instance de celui-ci est créé. Notez que le type de données utilisé est un ULONG qui correspond au type de valeur de propriété requis par la propriété ENCAPIPARAM_BITRATE. Cette valeur est l’encodage par défaut « Débit binaire » affiché dans la page de propriétés de l’encodeur :
const ULONG BitRateValues [] = {
1000000
};
Spécifiez la liste des plages juridiques et une valeur par défaut pour la propriété ENCAPIPARAM_BITRATE :
const KSPROPERTY_MEMBERSLIST BitRateMembersList [] = {
{
{
KSPROPERTY_MEMBER_STEPPEDRANGES,
sizeof (BitRateRanges),
SIZEOF_ARRAY (BitRateRanges),
0
},
BitRateRanges
},
{
{
KSPROPERTY_MEMBER_VALUES,
sizeof (BitRateValues),
SIZEOF_ARRAY (BitRateValues),
KSPROPERTY_MEMBER_FLAG_DEFAULT
},
BitRateValues
}
};
const KSPROPERTY_VALUES BitRateValuesSet = {
{
STATICGUIDOF (KSPROPTYPESETID_General),
VT_UI4,
0
},
SIZEOF_ARRAY (BitRateMembersList),
BitRateMembersList
};
Spécifiez la propriété unique définie pour le jeu de propriétés ENCAPIPARAM_BITRATE :
DEFINE_KSPROPERTY_TABLE(ENCAPI_BitRate) {
DEFINE_KSPROPERTY_ITEM (
0,
GetBitRateHandler, //Get-property handler supported
sizeof (KSPROPERTY),
sizeof (ULONG),
SetBitRateHandler, //Set-property handler supported
&BitRateValuesSet,
0,
NULL,
NULL,
sizeof (ULONG)
)
};
Notes
Le gestionnaire get-property retourne le débit binaire d’encodage, et le gestionnaire set-property doit vérifier que la valeur entrante transmise est valide avant de l’utiliser.
Implémentation des modes de débit binaire d’encodage pris en charge
Les extraits de code suivants montrent comment implémenter la prise en charge de la propriété ENCAPIPARAM_BITRATE_MODE .
Définissez les modes d’encodage pris en charge par l’encodeur :
const VIDEOENCODER_BITRATE_MODE BitRateModeValues [] = {
ConstantBitRate,
VariableBitRateAverage
};
Spécifiez le mode de débit d’encodage par défaut comme débit variable moyen :
const VIDEOENCODER_BITRATE_MODE BitRateModeDefaultValues [] = {
VariableBitRateAverage
};
Spécifiez la liste des plages juridiques et la valeur par défaut pour la propriété ENCAPIPARAM_BITRATE_MODE :
const KSPROPERTY_MEMBERSLIST BitRateModeMembersList [] = {
{
{
KSPROPERTY_MEMBER_VALUES,
sizeof (BitRateModeValues),
SIZEOF_ARRAY (BitRateModeValues),
0
},
BitRateModeValues
},
{
{
KSPROPERTY_MEMBER_VALUES,
sizeof (BitRateModeDefaultValues),
SIZEOF_ARRAY (BitRateModeDefaultValues),
KSPROPERTY_MEMBER_FLAG_DEFAULT
},
BitRateModeDefaultValues
}
};
const KSPROPERTY_VALUES BitRateModeValuesSet = {
{
STATICGUIDOF (KSPROPTYPESETID_General),
VT_I4,
0
},
SIZEOF_ARRAY (BitRateModeMembersList),
BitRateModeMembersList
};
Spécifiez la propriété unique définie pour le jeu de propriétés ENCAPIPARAM_BITRATE_MODE :
DEFINE_KSPROPERTY_TABLE(ENCAPI_BitRateMode) {
DEFINE_KSPROPERTY_ITEM (
0,
GetBitRateModeHandler, //Get-property handler supported
sizeof (KSPROPERTY),
sizeof (VIDEOENCODER_BITRATE_MODE),
SetBitRateModeHandler, //Set-property handler supported
&BitRateModeValuesSet,
0,
NULL,
NULL,
sizeof (VIDEOENCODER_BITRATE_MODE)
)
};
Notes
Le gestionnaire get-property doit retourner le mode de débit d’encodage, et le gestionnaire set-property doit vérifier que la valeur transmise entrante est valide avant de l’utiliser.
Les jeux de propriétés sont ensuite spécifiés en tant que table Automation de la structure KSFILTER_DESCRIPTOR .
DEFINE_KSPROPERTY_SET_TABLE(PropertyTable) {
DEFINE_KSPROPERTY_SET(
&ENCAPIPARAM_BITRATE_MODE,
SIZEOF_ARRAY (ENCAPI_BitRateMode),
ENCAPI_BitRateMode,
0,
NULL
),
DEFINE_KSPROPERTY_SET(
&ENCAPIPARAM_BITRATE,
SIZEOF_ARRAY (ENCAPI_BitRate),
ENCAPI_BitRate,
0,
NULL
)
};
DEFINE_KSAUTOMATION_TABLE(FilterTestTable) {
DEFINE_KSAUTOMATION_PROPERTIES(PropertyTable),
DEFINE_KSAUTOMATION_METHODS_NULL,
DEFINE_KSAUTOMATION_EVENTS_NULL
};
const
KSFILTER_DESCRIPTOR
FilterDescriptor = {
...,
&FilterTestTable, // Automation Table
...,
...
};
Spécification des fonctionnalités de l’encodeur dans le Registre
L’exemple de code suivant montre comment créer une clé de Registre Capabilities sous la clé de Registre Paramètres de l’appareil et comment créer et spécifier des sous-clés et des valeurs sous la clé Fonctionnalités . Exécutez ce code lorsque le pilote s’initialise.
Notes
Le code suivant suppose la présence d’un encodeur matériel unique par appareil physique. Si votre matériel contient plusieurs encodeurs, vous devez itérer dans la liste retournée dans l’appel à la fonction IoGetDeviceInterfaces et inscrire les fonctionnalités de chaque encodeur.
/**************************************************************************
CreateDwordValueInCapabilityRegistry()
IN Pdo: PhysicalDeviceObject
IN categoryGUID: Category GUID eg KSCATEGORY_CAPTURE
1. Get Symbolic name for interface
2. Open registry key for storing information about a
particular device interface instance
3. Create Capabilities key under "Device Parameters" key
4. Create a DWORD value "TestCapValueDWORD" under Capabilities
Must be running at IRQL = PASSIVE_LEVEL in the context of a system thread
**************************************************************************/
NTSTATUS CreateDwordValueInCapabilityRegistry(IN PDEVICE_OBJECT pdo, IN GUID categoryGUID)
{
// 1. Get Symbolic name for interface
// pSymbolicNameList can contain multiple strings if pdo is NULL.
// Driver should parse this list of string to get
// the one corresponding to current device interface instance.
PWSTR pSymbolicNameList = NULL;
NTSTATUS ntStatus = IoGetDeviceInterfaces(
&categoryGUID,
pdo,
DEVICE_INTERFACE_INCLUDE_NONACTIVE,
&pSymbolicNameList);
if (NT_SUCCESS(ntStatus) && (NULL != pSymbolicNameList))
{
HANDLE hDeviceParametersKey = NULL;
UNICODE_STRING symbolicName;
// 2. Open registry key for storing information about a
// particular device interface instance
RtlInitUnicodeString(&symbolicName, pSymbolicNameList);
ntStatus = IoOpenDeviceInterfaceRegistryKey(
&symbolicName,
KEY_READ|KEY_WRITE,
&hDeviceParametersKey);
if (NT_SUCCESS(ntStatus))
{
OBJECT_ATTRIBUTES objAttribSubKey;
UNICODE_STRING subKey;
// 3. Create Capabilities key under "Device Parameters" key
RtlInitUnicodeString(&subKey,L"Capabilities");
InitializeObjectAttributes(&objAttribSubKey,
&subKey,
OBJ_KERNEL_HANDLE,
hDeviceParametersKey,
NULL);
HANDLE hCapabilityKeyHandle = NULL;
ntStatus = ZwCreateKey(&hCapabilityKeyHandle,
KEY_READ|KEY_WRITE|KEY_SET_VALUE,
&objAttribSubKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
NULL);
if (NT_SUCCESS(ntStatus))
{
OBJECT_ATTRIBUTES objAttribDwordKeyVal;
UNICODE_STRING subValDword;
// 4. Create a DWORD value "TestCapValueDWORD" under Capabilities
RtlInitUnicodeString(&subValDword,L"TestCapValueDWORD");
ULONG data = 0xaaaaaaaa;
ntStatus = ZwSetValueKey(hCapabilityKeyHandle,&subValDword,0,REG_DWORD,&data,sizeof(ULONG));
ZwClose(hCapabilityKeyHandle);
}
}
ZwClose(hDeviceParametersKey);
ExFreePool(pSymbolicNameList);
}
return ntStatus;
}