Exemplos de código do codificador
Os exemplos de código a seguir são baseados no AVSHwS (Driver de Exemplo de Hardware Simulado) do AVStream. Eles demonstram o seguinte:
Como especificar as taxas de bits com suporte do codificador
Como especificar os modos de codificação de taxa de bits compatíveis com um codificador
Como especificar valores de metadados em tempo de execução na chave do Registro Device Parameters\Capabilities do dispositivo codificador
Implementando taxas de bits com suporte
Os snippets de código a seguir demonstram como implementar o suporte para a propriedade ENCAPIPARAM_BITRATE . Use uma estrutura KSPROPERTY_STEPPING_LONG para especificar uma granularidade de 400 bits por segundo (bps) com um limite inferior de 400 bps e 4.000.000 bps de limite superior.
const KSPROPERTY_STEPPING_LONG BitRateRanges [] = {
{
400,
0,
400,
4000000
}
};
Se você acessar a página de propriedades do filtro de codificador clicando com o botão direito do mouse no filtro em uma ferramenta como GraphEdit, verá a barra deslizante Taxa de Bits em que esses valores são usados.
Em seguida, especifique a taxa de bits de codificação padrão do filtro do codificador quando uma instância dele for criada. Observe que o tipo de dados usado é um ULONG que corresponde ao tipo de valor da propriedade exigido pela propriedade ENCAPIPARAM_BITRATE. Esse valor é a codificação padrão "Taxa de Bits" exibida na página de propriedades do codificador:
const ULONG BitRateValues [] = {
1000000
};
Especifique a lista de intervalos legais e um valor padrão para a propriedade 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
};
Especifique a única propriedade definida para o conjunto de propriedades 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)
)
};
Observação
O manipulador get-property retorna a taxa de bits de codificação e o manipulador Set-property deve testar se o valor de entrada passada é válido antes de usá-lo.
Implementando modos de taxa de bits de codificação com suporte
Os snippets de código a seguir demonstram como implementar o suporte para a propriedade ENCAPIPARAM_BITRATE_MODE .
Defina os modos de codificação compatíveis com o codificador:
const VIDEOENCODER_BITRATE_MODE BitRateModeValues [] = {
ConstantBitRate,
VariableBitRateAverage
};
Especifique o modo de taxa de bits de codificação padrão como taxa média de bits variáveis:
const VIDEOENCODER_BITRATE_MODE BitRateModeDefaultValues [] = {
VariableBitRateAverage
};
Especifique a lista de intervalos legais e o valor padrão para a propriedade 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
};
Especifique a única propriedade definida para o conjunto de propriedades 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)
)
};
Observação
O manipulador get-property deve retornar o modo de taxa de bits de codificação e o manipulador Set-property deve testar se o valor de entrada passado é válido antes de usá-lo.
Os conjuntos de propriedades são especificados como a tabela de automação da estrutura 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
...,
...
};
Especificando os recursos do codificador no Registro
O exemplo de código a seguir demonstra como criar uma chave do Registro de funcionalidades na chave do Registro de Parâmetros do Dispositivo e como criar e especificar subchaves e valores na chave Funcionalidades . Execute esse código quando o driver for inicializado.
Observação
O código a seguir pressupõe a presença de um único codificador de hardware por dispositivo físico. Se o hardware contiver mais de um codificador, você deverá iterar pela lista retornada na chamada para a função IoGetDeviceInterfaces e registrar os recursos para cada codificador.
/**************************************************************************
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;
}